You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by zo...@apache.org on 2011/02/27 21:20:30 UTC

svn commit: r1075132 [15/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...

Added: aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/impl/ApplicationMetadataImpl.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/impl/ApplicationMetadataImpl.java?rev=1075132&view=auto
==============================================================================
--- aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/impl/ApplicationMetadataImpl.java (added)
+++ aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/impl/ApplicationMetadataImpl.java Sun Feb 27 20:20:13 2011
@@ -0,0 +1,237 @@
+/*
+ * 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.impl;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+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.ServiceDeclaration;
+import org.apache.aries.application.utils.AppConstants;
+import org.apache.aries.application.utils.manifest.ManifestHeaderProcessor;
+import org.apache.aries.application.utils.manifest.ManifestHeaderProcessor.NameValueMap;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.Version;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Implementation of ApplicationMetadata and DeploymentMetadata
+ *
+ */
+public final class ApplicationMetadataImpl implements ApplicationMetadata
+{
+  private static final Logger _logger = LoggerFactory.getLogger("org.apache.aries.application.management.impl");
+  private String appSymbolicName;
+  private Version appVersion;
+  private String appName;
+  private String appScope;
+  private List<Content> appContents;
+  private List<ServiceDeclaration> importServices;
+  private List<ServiceDeclaration> exportServices;
+  private Manifest manifest;
+  private List<Content> useBundle;
+  /**
+   * create the applicationMetadata from appManifest
+   * @param appManifest   the Application.mf manifest
+   */
+  public ApplicationMetadataImpl(Manifest appManifest) {
+
+    this.appContents = new ArrayList<Content>();
+    this.useBundle = new ArrayList<Content>();    
+    this.importServices = new ArrayList<ServiceDeclaration>();
+    this.exportServices = new ArrayList<ServiceDeclaration>();    
+    setup(appManifest);
+    
+    // As of 7 Jan 2010 we have no setter methods. Hence it's currently 
+    // fine to keep a copy of appManifest, and to use it in the store()
+    // method.
+    manifest = appManifest;
+  }
+  
+  /**
+   * setup the application metadata from the appManifest
+   * @param appManifest     application.mf manifest
+   */
+  private void setup(Manifest appManifest) 
+  {
+    Map<String, String> appMap = readManifestIntoMap(appManifest);
+    
+    // configure the appSymbolicName and appVersion
+    this.appSymbolicName = appMap.get(AppConstants.APPLICATION_SYMBOLIC_NAME);
+    this.appVersion = new Version(appMap.get(AppConstants.APPLICATION_VERSION));
+    this.appName = appMap.get(AppConstants.APPLICATION_NAME);
+    this.appScope = this.appSymbolicName + "_" + this.appVersion.toString();
+    
+    if (this.appSymbolicName == null || this.appVersion == null) {
+      throw new IllegalArgumentException("Failed to create ApplicationMetadataImpl object from Manifest " + appManifest);
+    }
+    
+    // configure appContents
+ // use parseImportString as we don't allow appContents to be duplicate
+    String applicationContents = appMap.get(AppConstants.APPLICATION_CONTENT);
+    Map<String, NameValueMap<String, String>> appContentsMap = ManifestHeaderProcessor.parseImportString(applicationContents);
+    for (Map.Entry<String, NameValueMap<String, String>> e : appContentsMap.entrySet()) {
+      this.appContents.add(new ContentImpl(e.getKey(), e.getValue()));
+    }
+   
+    String useBundleStr = appMap.get(AppConstants.APPLICATION_USE_BUNDLE);
+    if (useBundleStr != null) {
+      Map<String, NameValueMap<String, String>> useBundleMap = ManifestHeaderProcessor.parseImportString(useBundleStr);
+    for (Map.Entry<String, NameValueMap<String, String>> e : useBundleMap.entrySet()) {
+        this.useBundle.add(new ContentImpl(e.getKey(), e.getValue()));
+      }
+    }
+    
+    String allServiceImports = appMap.get(AppConstants.APPLICATION_IMPORT_SERVICE);
+    List<String> serviceImports = ManifestHeaderProcessor.split(allServiceImports, ",");
+    for (String s: serviceImports) { 
+      try { 
+        ServiceDeclaration dec = new ServiceDeclarationImpl(s);
+        importServices.add(dec);
+      } catch (InvalidSyntaxException ise) { 
+        _logger.warn("APPUTILS0013E", new Object[] {s, appSymbolicName});
+      }
+    }
+    
+    String allServiceExports = appMap.get(AppConstants.APPLICATION_EXPORT_SERVICE);
+    List<String> serviceExports = ManifestHeaderProcessor.split(allServiceExports, ",");
+    for (String s: serviceExports) { 
+      try { 
+        ServiceDeclaration dec = new ServiceDeclarationImpl(s);
+        exportServices.add(dec);
+      } catch (InvalidSyntaxException ise) { 
+        _logger.warn("APPUTILS0014E", new Object[] {s, appSymbolicName});
+      }
+    }
+    
+  }
+  
+  /**
+   * Reads a manifest's main attributes into a String->String map.
+   * <p>
+   * Will always return a map, empty if the manifest had no attributes.
+   * 
+   * @param mf The manifest to read.
+   * @return Map of manifest main attributes.
+   */
+  private Map<String, String> readManifestIntoMap(Manifest mf){   
+    HashMap<String, String> props = new HashMap<String, String>();
+    
+    Attributes mainAttrs = mf.getMainAttributes();
+    if (mainAttrs!=null){
+      Set<Entry<Object, Object>> attributeSet =  mainAttrs.entrySet(); 
+      if (attributeSet != null){
+        // Copy all the manifest headers across. The entry set should be a set of
+        // Name to String mappings, by calling String.valueOf we do the conversion
+        // to a string and we do not NPE.
+        for (Map.Entry<Object, Object> entry : attributeSet) {
+          props.put(String.valueOf(entry.getKey()), String.valueOf(entry.getValue()));
+        }
+      }    
+    }
+       
+    return props;
+  }  
+    
+  public List<Content> getApplicationContents()
+  {
+    return Collections.unmodifiableList(this.appContents);
+  }
+
+  public List<ServiceDeclaration> getApplicationExportServices()
+  {
+    return Collections.unmodifiableList(this.exportServices);
+  }
+
+  public List<ServiceDeclaration> getApplicationImportServices()
+  {
+    return Collections.unmodifiableList(this.importServices);
+  }
+
+  public String getApplicationSymbolicName()
+  {
+    return this.appSymbolicName;
+  }
+
+  public Version getApplicationVersion()
+  {
+    return this.appVersion;
+  }
+
+  public String getApplicationName() 
+  {
+    return this.appName;
+  }
+  
+  public String getApplicationScope() 
+  {
+    return appScope;
+  }
+  
+  public boolean equals(Object other)
+  {
+    if (other == this) return true;
+    if (other == null) return false;
+    if (other instanceof ApplicationMetadataImpl) {
+      return appScope.equals(((ApplicationMetadataImpl)other).appScope);
+    }
+    
+    return false;
+  }
+  
+  public int hashCode()
+  {
+    return appScope.hashCode();
+  }
+
+  public void store(File f) throws IOException {
+    FileOutputStream fos = new FileOutputStream (f);
+    store(fos);
+    fos.close();
+  }
+
+  public void store(OutputStream out) throws IOException {
+    if (manifest != null) {
+      Attributes att = manifest.getMainAttributes();
+      if ((att.getValue(Attributes.Name.MANIFEST_VERSION.toString())) == null) {
+        att.putValue(Attributes.Name.MANIFEST_VERSION.toString(), AppConstants.MANIFEST_VERSION);
+      }
+      manifest.write(out);
+    }
+  }
+
+  public Collection<Content> getUseBundles()
+  {
+    return this.useBundle;
+  }
+}
\ No newline at end of file

Added: aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/impl/ContentImpl.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/impl/ContentImpl.java?rev=1075132&view=auto
==============================================================================
--- aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/impl/ContentImpl.java (added)
+++ aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/impl/ContentImpl.java Sun Feb 27 20:20:13 2011
@@ -0,0 +1,205 @@
+/*
+ * 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.impl;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.aries.application.Content;
+import org.apache.aries.application.VersionRange;
+import org.apache.aries.application.utils.internal.MessageUtil;
+import org.apache.aries.application.utils.manifest.ManifestHeaderProcessor;
+import org.apache.aries.application.utils.manifest.ManifestHeaderProcessor.NameValueMap;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Version;
+
+
+/**
+ * Implementation of Content
+ *
+ */
+public final class ContentImpl implements Content
+{
+  private String contentName;
+  protected Map<String, String> attributes;
+  private Map<String, String> directives;
+  private NameValueMap<String, String> nameValueMap;
+  
+  /**
+   * 
+   * @param content  Application-Content, Import-Package content
+   */
+  public ContentImpl(String content) {
+    Map<String, NameValueMap<String, String>> appContentsMap = ManifestHeaderProcessor.parseImportString(content);
+    if (appContentsMap.size() != 1) {
+      throw new IllegalArgumentException(MessageUtil.getMessage("APPUTILS0004E",content));
+    }
+    for (Map.Entry<String, NameValueMap<String, String>> entry : appContentsMap.entrySet()) {
+      this.contentName = entry.getKey();
+      this.nameValueMap= entry.getValue();
+      setup();
+      break;
+    }
+  }
+  
+  public ContentImpl (String bundleSymbolicName, Version version) { 
+    this.contentName = bundleSymbolicName;
+    this.nameValueMap = new NameValueMap<String, String>();
+    nameValueMap.put("version", version.toString());
+    setup();
+  }
+  
+  public ContentImpl (String bundleSymbolicName, VersionRange version) { 
+    this.contentName = bundleSymbolicName;
+    this.nameValueMap = new NameValueMap<String, String>();
+    nameValueMap.put("version", version.toString());
+    setup();
+  }
+  /**
+   * 
+   * @param contentName  
+   * @param nameValueMap
+   */
+  public ContentImpl(String contentName, NameValueMap<String, String> nameValueMap) {
+    this.contentName = contentName;
+    this.nameValueMap= nameValueMap;
+    setup();
+  }
+  
+  public String getContentName() {
+    return this.contentName;
+  }
+  
+  public Map<String, String> getAttributes() {
+    return Collections.unmodifiableMap(this.attributes);
+  }
+  
+  public Map<String, String> getDirectives() {
+    return Collections.unmodifiableMap(this.directives);
+  }
+  
+  public String getAttribute(String key) {
+    String toReturn = this.attributes.get(key);
+    return toReturn;
+  }
+  
+  /**
+   * add key value to the attributes map
+   * @param key
+   * @param value
+   */
+  public void addAttribute(String key, String value) {
+    this.attributes.put(key, value);
+  }
+  
+  public String getDirective(String key) {
+    String toReturn = this.directives.get(key);
+    return toReturn;
+  }
+  
+  public NameValueMap<String, String> getNameValueMap() {
+    NameValueMap<String, String> nvm = new NameValueMap<String, String>();
+    for (String key : this.nameValueMap.keySet()) {
+      nvm.addToCollection(key, this.nameValueMap.get(key));
+    }
+    return nvm;
+  }
+  
+  /**
+   * add key value to the directives map
+   * @param key
+   * @param value
+   */
+  public void addDirective(String key, String value) {
+    this.directives.put(key, value);
+  }
+  
+  public VersionRange getVersion() {
+    VersionRange vi = null;
+    if (this.attributes.get(Constants.VERSION_ATTRIBUTE) != null 
+        && this.attributes.get(Constants.VERSION_ATTRIBUTE).length() > 0) {
+      vi = ManifestHeaderProcessor.parseVersionRange(this.attributes.get(Constants.VERSION_ATTRIBUTE));
+    } else {
+      // what if version is not specified?  let's interpret it as 0.0.0 
+      vi = ManifestHeaderProcessor.parseVersionRange("0.0.0");
+    }
+    return vi;
+  }
+  
+  @Override
+  public String toString()
+  {
+    return this.contentName + ";" + this.nameValueMap.toString();
+  }
+  
+  @Override
+  public boolean equals(Object other)
+  {
+    if (other == this) return true;
+    if (other == null) return false;
+    
+    if (other instanceof ContentImpl) {
+      ContentImpl otherContent = (ContentImpl)other;
+      
+      Map<String,String> attributesWithoutVersion = attributes;
+      
+      if (attributes.containsKey("version")) {
+        attributesWithoutVersion = new HashMap<String, String>(attributes);
+        attributesWithoutVersion.remove("version");
+      }
+      
+      Map<String, String> otherAttributesWithoutVersion = otherContent.attributes;
+      
+      if (otherContent.attributes.containsKey("version")) {
+        otherAttributesWithoutVersion = new HashMap<String, String>(otherContent.attributes);
+        otherAttributesWithoutVersion.remove("version");
+      }
+      
+      return contentName.equals(otherContent.contentName) && 
+             attributesWithoutVersion.equals(otherAttributesWithoutVersion) &&
+             directives.equals(otherContent.directives) &&
+             getVersion().equals(otherContent.getVersion());
+    }
+    
+    return false;
+  }
+  
+  @Override
+  public int hashCode()
+  {
+    return contentName.hashCode();
+  }
+  
+  /**
+   * set up directives and attributes
+   */
+  protected void setup() {
+    this.attributes = new HashMap<String, String>();
+    this.directives = new HashMap<String, String>();
+    
+    for (String key : this.nameValueMap.keySet()) {
+      if (key.endsWith(":")) {
+        this.directives.put(key.substring(0, key.length() - 1), this.nameValueMap.get(key));
+      } else {
+        this.attributes.put(key, this.nameValueMap.get(key));
+      }
+    }
+  }
+}

Added: aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/impl/DeploymentContentImpl.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/impl/DeploymentContentImpl.java?rev=1075132&view=auto
==============================================================================
--- aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/impl/DeploymentContentImpl.java (added)
+++ aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/impl/DeploymentContentImpl.java Sun Feb 27 20:20:13 2011
@@ -0,0 +1,115 @@
+/*
+ * 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.impl;
+
+import java.util.Map;
+
+import org.apache.aries.application.DeploymentContent;
+import org.apache.aries.application.VersionRange;
+import org.apache.aries.application.utils.AppConstants;
+import org.apache.aries.application.utils.manifest.ManifestHeaderProcessor;
+import org.apache.aries.application.utils.manifest.ManifestHeaderProcessor.NameValueMap;
+import org.osgi.framework.Version;
+
+public final class DeploymentContentImpl implements DeploymentContent {
+  
+  private ContentImpl _content;
+  
+  /**
+   * DeploymentContent relates to a bundle at a particular version. 
+   * We can therefore assume that the Version passed into this 
+   * constructor is the exact version in question. 
+   * @param bundleSymbolicName
+   * @param version
+   */
+  public DeploymentContentImpl (String bundleSymbolicName, Version version) {
+    NameValueMap<String, String> nvMap = new NameValueMap<String, String>();
+    nvMap.put(AppConstants.DEPLOYMENT_BUNDLE_VERSION, version.toString());
+    _content = new ContentImpl (bundleSymbolicName, nvMap);
+  }
+  
+  /**
+   * Construct a DeploymentContent from a string of the form, 
+   *   bundle.symbolic.name;deployedContent="1.2.3"
+   * @param deployedContent
+   */
+  public DeploymentContentImpl (String deployedContent) {
+    _content = new ContentImpl (deployedContent);
+  }
+  
+  public Version getExactVersion() {
+    return getVersion().getExactVersion();
+  }
+
+  public String getAttribute(String key) {
+    return _content.getAttribute(key);
+  }
+
+  public Map<String, String> getAttributes() {
+    return _content.getAttributes();
+  }
+
+  public String getContentName() {
+    return _content.getContentName();
+  }
+
+  public String getDirective(String key) {
+    return _content.getDirective(key);
+  }
+
+  public Map<String, String> getDirectives() {
+    return _content.getDirectives();
+  }
+
+  public VersionRange getVersion() {
+    String deployedVersion = _content.getAttribute(AppConstants.DEPLOYMENT_BUNDLE_VERSION);
+    VersionRange vr = null;
+    if (deployedVersion != null && deployedVersion.length() > 0) {
+      vr = ManifestHeaderProcessor.parseVersionRange(deployedVersion, true);
+    }
+    return vr;
+  }
+
+  @Override
+  public boolean equals(Object other) { 
+    if (other == null) 
+      return false;
+    if (this == other) 
+      return true;
+    if (other instanceof DeploymentContentImpl) {
+      return _content.equals(((DeploymentContentImpl) other)._content);
+    } else { 
+      return false;
+    }
+  }
+  
+  public int hashCode() {
+    return _content.hashCode();
+  }
+
+  public Map<String, String> getNameValueMap() {
+    return _content.getNameValueMap();
+  }
+  
+  public String toString()
+  {
+    return _content.toString();
+  }
+}

Added: aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/impl/DeploymentMetadataFactoryImpl.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/impl/DeploymentMetadataFactoryImpl.java?rev=1075132&view=auto
==============================================================================
--- aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/impl/DeploymentMetadataFactoryImpl.java (added)
+++ aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/impl/DeploymentMetadataFactoryImpl.java Sun Feb 27 20:20:13 2011
@@ -0,0 +1,78 @@
+/*
+ * 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.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Set;
+import java.util.jar.Manifest;
+
+import org.apache.aries.application.DeploymentMetadata;
+import org.apache.aries.application.DeploymentMetadataFactory;
+import org.apache.aries.application.InvalidAttributeException;
+import org.apache.aries.application.filesystem.IFile;
+import org.apache.aries.application.management.AriesApplication;
+import org.apache.aries.application.management.BundleInfo;
+import org.apache.aries.application.management.ResolverException;
+import org.apache.aries.application.utils.manifest.ManifestProcessor;
+
+public class DeploymentMetadataFactoryImpl implements DeploymentMetadataFactory
+{
+
+  public DeploymentMetadata createDeploymentMetadata(AriesApplication app,
+      Set<BundleInfo> additionalBundlesRequired) throws ResolverException
+  {
+    return new DeploymentMetadataImpl(app, additionalBundlesRequired);
+  }
+
+  public DeploymentMetadata parseDeploymentMetadata(IFile src) throws IOException
+  {
+    InputStream is = src.open();
+    try {
+      return parseDeploymentMetadata(is);
+    } finally {
+      is.close();
+    }
+  }
+
+  public DeploymentMetadata parseDeploymentMetadata(InputStream in) throws IOException
+  {
+    return createDeploymentMetadata(ManifestProcessor.parseManifest(in));
+  }
+
+  public DeploymentMetadata createDeploymentMetadata(Manifest manifest) throws IOException
+  {
+    try {
+      return new DeploymentMetadataImpl(manifest);
+    } catch (InvalidAttributeException iae) {
+      throw new IOException(iae);
+    }
+  }
+
+  public DeploymentMetadata createDeploymentMetadata(IFile src) throws IOException
+  {
+    return parseDeploymentMetadata(src);
+  }
+
+  public DeploymentMetadata createDeploymentMetadata(InputStream in) throws IOException
+  {
+    return parseDeploymentMetadata(in);
+  }
+}

Added: aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/impl/DeploymentMetadataImpl.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/impl/DeploymentMetadataImpl.java?rev=1075132&view=auto
==============================================================================
--- aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/impl/DeploymentMetadataImpl.java (added)
+++ aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/impl/DeploymentMetadataImpl.java Sun Feb 27 20:20:13 2011
@@ -0,0 +1,354 @@
+/*
+ * 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.impl;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+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 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.DeploymentContent;
+import org.apache.aries.application.DeploymentMetadata;
+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.ResolverException;
+import org.apache.aries.application.utils.AppConstants;
+import org.apache.aries.application.utils.FilterUtils;
+import org.apache.aries.application.utils.manifest.ManifestProcessor;
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.Version;
+
+public class DeploymentMetadataImpl implements DeploymentMetadata {
+  private ApplicationMetadata _applicationMetadata;
+  private List<DeploymentContent> _deploymentContent = new ArrayList<DeploymentContent>();
+  private List<DeploymentContent> _provisionSharedContent = new ArrayList<DeploymentContent>();
+  private List<DeploymentContent> _deployedUseBundleContent = new ArrayList<DeploymentContent>();
+  
+  private Set<Content> _deploymentImportPackage = new HashSet<Content>();
+  private Map<String, String> _deploymentCustomEntries = new HashMap<String, String>();  
+  private Map<String, String> _deploymentEntries = new HashMap<String, String>();
+  private Collection<Filter> _deployedImportService = new ArrayList<Filter>();
+  
+  public DeploymentMetadataImpl (AriesApplication app, Set<BundleInfo> bundlesRequired) throws ResolverException
+  {
+    _applicationMetadata = app.getApplicationMetadata();
+    _deploymentContent = new ArrayList<DeploymentContent>();
+    _provisionSharedContent = new ArrayList<DeploymentContent>();
+    _deployedUseBundleContent = new ArrayList<DeploymentContent>();
+    
+    Map<String, VersionRange> appContent = new HashMap<String, VersionRange>();
+    
+    for (Content c : app.getApplicationMetadata().getApplicationContents()) {
+      appContent.put(c.getContentName(), c.getVersion());
+    }
+    
+    Map<String, VersionRange> useBundles = new HashMap<String, VersionRange>();
+    for (Content c : app.getApplicationMetadata().getUseBundles()) {
+      useBundles.put(c.getContentName(), c.getVersion());
+    }
+    
+    for (BundleInfo info : bundlesRequired) {
+      
+      VersionRange appContentRange = appContent.get(info.getSymbolicName());
+      VersionRange useBundleRange = useBundles.get(info.getSymbolicName());
+      DeploymentContent dp = new DeploymentContentImpl(info.getSymbolicName(), info.getVersion());
+      
+      if ((appContentRange == null) && (useBundleRange == null)){
+        _provisionSharedContent.add(dp);
+      } else if (appContentRange.matches(info.getVersion())) {
+        _deploymentContent.add(dp);
+      }  else if (useBundleRange.matches(info.getVersion())) {
+        _deployedUseBundleContent.add(dp);
+      }
+      else {
+        throw new ResolverException("Bundle " + info.getSymbolicName() + " at version " + info.getVersion() + " is not in the range " + appContentRange + " or " + useBundleRange);
+      }
+    }
+  }
+  
+  /**
+   * Construct a DeploymentMetadata from Manifest
+   * @param src
+   * @throws IOException
+   */
+  public DeploymentMetadataImpl(Manifest mf) throws InvalidAttributeException{ 
+    _applicationMetadata = new ApplicationMetadataImpl (mf);
+
+    Attributes attributes = mf.getMainAttributes();
+      
+    parseDeploymentContent(attributes.getValue(AppConstants.DEPLOYMENT_CONTENT), _deploymentContent);
+    parseDeploymentContent(attributes.getValue(AppConstants.DEPLOYMENT_PROVISION_BUNDLE), _provisionSharedContent);
+    parseDeploymentContent(attributes.getValue(AppConstants.DEPLOYMENT_USE_BUNDLE), _deployedUseBundleContent);
+    parseContent(attributes.getValue(AppConstants.DEPLOYMENT_IMPORT_PACKAGES), _deploymentImportPackage);
+    
+    _deployedImportService = getFilters(attributes.getValue(AppConstants.DEPLOYMENTSERVICE_IMPORT));
+    _deploymentCustomEntries = getCustomEntries(attributes);
+    _deploymentEntries = getEntries(attributes);
+  }
+  
+  public DeploymentMetadataImpl(Map<String, String> map) throws InvalidAttributeException{ 
+
+    Attributes attributes = new Attributes();
+    if (map != null) {
+    for (Map.Entry<String, String> entry : map.entrySet()) {
+      attributes.putValue(entry.getKey(), entry.getValue());
+    }
+    }
+    parseDeploymentContent(map.get(AppConstants.DEPLOYMENT_CONTENT), _deploymentContent);
+    parseDeploymentContent(map.get(AppConstants.DEPLOYMENT_PROVISION_BUNDLE), _provisionSharedContent);
+    parseDeploymentContent(map.get(AppConstants.DEPLOYMENT_USE_BUNDLE), _deployedUseBundleContent);
+    parseContent(attributes.getValue(AppConstants.DEPLOYMENT_IMPORT_PACKAGES), _deploymentImportPackage);
+    _deployedImportService = getFilters(attributes.getValue(AppConstants.DEPLOYMENTSERVICE_IMPORT));
+    _deploymentCustomEntries = getCustomEntries(attributes);
+    _deploymentEntries = getEntries(attributes);
+    
+  }
+
+  private Collection<Attributes.Name> getDeploymentStandardHeaders() {
+    Collection<Attributes.Name> standardKeys = new HashSet<Attributes.Name> ();
+    standardKeys.add(new Attributes.Name(AppConstants.APPLICATION_MANIFEST_VERSION));
+    standardKeys.add(new Attributes.Name(AppConstants.DEPLOYMENT_CONTENT));
+    standardKeys.add(new Attributes.Name(AppConstants.DEPLOYMENT_PROVISION_BUNDLE));
+    standardKeys.add(new Attributes.Name(AppConstants.DEPLOYMENT_USE_BUNDLE));
+    standardKeys.add(new Attributes.Name(AppConstants.DEPLOYMENT_IMPORT_PACKAGES));
+    standardKeys.add(new Attributes.Name(AppConstants.DEPLOYMENTSERVICE_IMPORT));
+    standardKeys.add(new Attributes.Name(AppConstants.APPLICATION_SYMBOLIC_NAME));
+    standardKeys.add(new Attributes.Name(AppConstants.APPLICATION_VERSION));
+    return standardKeys;
+  }
+
+  private Collection<String> getCustomHeaders(Attributes attrs) {
+    
+    Collection<String> customKeys = new HashSet<String>();
+    Collection<Attributes.Name> standardKeys = getDeploymentStandardHeaders();
+    if ((attrs != null) && (!!!attrs.isEmpty())) {
+     Set<Object> keys = attrs.keySet();
+     
+     if ((keys != null) && (!!!keys.isEmpty())) {
+       for (Object eachKey : keys) {
+         String key = eachKey.toString();
+         customKeys.add(key);
+       }
+       
+         customKeys.removeAll(standardKeys);
+       
+     }
+    }
+    return customKeys;
+  }
+  
+  private String getContentsAsString (Collection<Content> contents) {
+    StringBuilder builder = new StringBuilder();
+    boolean beginning = true;
+    for (Content c : contents) {
+      if (!!!beginning) {
+        builder.append(",");
+      }
+      builder.append(c);
+      beginning = false;
+      
+    }
+    return builder.toString();
+  }
+  
+  public List<DeploymentContent> getApplicationDeploymentContents() {
+    return Collections.unmodifiableList(_deploymentContent);
+  }
+  
+  public List<DeploymentContent> getApplicationProvisionBundles() {
+    return Collections.unmodifiableList(_provisionSharedContent);
+  }
+
+  public ApplicationMetadata getApplicationMetadata() {
+    return _applicationMetadata;
+  }
+
+  public String getApplicationSymbolicName() {
+    return _applicationMetadata.getApplicationSymbolicName();
+  }
+
+  public Version getApplicationVersion() {
+    return _applicationMetadata.getApplicationVersion();
+  }
+
+
+  public void store(File f) throws FileNotFoundException, IOException{
+    FileOutputStream fos = new FileOutputStream (f);
+    store(fos);
+    fos.close();
+  }
+
+  public void store(OutputStream out) throws IOException {
+    // We weren't built from a Manifest, so construct one. 
+    Manifest mf = new Manifest();
+    Attributes attributes = mf.getMainAttributes();
+    attributes.putValue(Attributes.Name.MANIFEST_VERSION.toString(), AppConstants.MANIFEST_VERSION);
+    attributes.putValue(AppConstants.APPLICATION_VERSION, getApplicationVersion().toString());
+    attributes.putValue(AppConstants.APPLICATION_SYMBOLIC_NAME, getApplicationSymbolicName());
+    if ((_deploymentContent != null) && (!_deploymentContent.isEmpty())) {
+      attributes.putValue(AppConstants.DEPLOYMENT_CONTENT, getDeploymentContentsAsString(_deploymentContent));
+    }
+    if ((_provisionSharedContent != null) && (!_provisionSharedContent.isEmpty())) {
+      attributes.putValue(AppConstants.DEPLOYMENT_PROVISION_BUNDLE, getDeploymentContentsAsString(_provisionSharedContent));
+    }
+    if ((_deployedUseBundleContent != null) && (!_deployedUseBundleContent.isEmpty())) {
+      attributes.putValue(AppConstants.DEPLOYMENT_USE_BUNDLE, getDeploymentContentsAsString(_deployedUseBundleContent));
+    }
+    if ((_deploymentImportPackage != null) && (!_deploymentImportPackage.isEmpty())) {
+      attributes.putValue(AppConstants.DEPLOYMENT_IMPORT_PACKAGES, getContentsAsString(_deploymentImportPackage));
+    }
+    if ((_deployedImportService != null) && (!!!_deployedImportService.isEmpty())) {
+      attributes.putValue(AppConstants.DEPLOYMENTSERVICE_IMPORT, convertFiltersToString(_deployedImportService, ",") );
+    }
+    // let's write out the custom headers
+    if ((_deploymentCustomEntries != null) && (_deploymentCustomEntries.isEmpty())) {
+      for (Map.Entry<String, String> customEntry : _deploymentCustomEntries.entrySet()) {
+        attributes.putValue(customEntry.getKey(), customEntry.getValue());
+      }
+    }
+    mf.write(out);
+  }
+  
+  
+  
+  private String getDeploymentContentsAsString (List<DeploymentContent> content) { 
+    StringBuilder builder = new StringBuilder();
+    for (DeploymentContent dc : content) {
+      builder.append(dc.getContentName());
+      builder.append(';' + AppConstants.DEPLOYMENT_BUNDLE_VERSION + "=");
+      builder.append(dc.getExactVersion());
+      builder.append(",");
+    }
+    if (builder.length() > 0) { 
+      builder.deleteCharAt(builder.length() - 1);
+    }
+    return builder.toString();
+  }
+
+  private void parseDeploymentContent(String content, List<DeploymentContent> contents)
+  {
+    List<String> pcList = ManifestProcessor.split(content, ",");
+    for (String s : pcList) {
+      contents.add(new DeploymentContentImpl(s));
+    }
+  }
+
+  private void parseContent(String content, Collection<Content> contents)
+  {
+    List<String> pcList = ManifestProcessor.split(content, ",");
+    for (String s : pcList) {
+      contents.add(new ContentImpl(s));
+    }
+  }
+  
+
+  public List<DeploymentContent> getDeployedUseBundle()
+  {
+    return Collections.unmodifiableList(_deployedUseBundleContent);
+  }
+
+  public Set<Content> getImportPackage()
+  {
+    return Collections.unmodifiableSet(_deploymentImportPackage);
+  }
+
+  public Collection<Filter> getDeployedServiceImport() 
+  {
+    return Collections.unmodifiableCollection(_deployedImportService);
+  }
+
+  public Map<String, String> getHeaders()
+  {
+    return Collections.unmodifiableMap(_deploymentEntries);
+  }
+  
+  private Map<String, String> getEntries(Attributes attrs) {
+    Map<String, String> entries = new HashMap<String, String>();
+    if ((attrs != null) && (!attrs.isEmpty())) {
+      Set<Object> keys = attrs.keySet();
+      for (Object key : keys) {
+        entries.put(key.toString(),  attrs.getValue((Attributes.Name)key));
+      }
+    }
+    return entries;
+  }
+ 
+
+  private Map<String, String> getCustomEntries(Attributes attrs) {
+    Map<String, String> customEntry = new HashMap<String, String> ();
+    Collection<String> customHeaders = getCustomHeaders(attrs);
+    if ((customHeaders != null) && (customHeaders.isEmpty())) {
+      for (String customHeader : customHeaders)
+        customEntry.put(customHeader, attrs.getValue(customHeader));
+      
+    }
+    return customEntry;
+    
+  }
+  
+   private Collection<Filter> getFilters(String filterString) throws InvalidAttributeException{
+     Collection<Filter> filters = new ArrayList<Filter>();
+     List<String> fs = ManifestProcessor.split(filterString, ",");
+     if ((fs != null) && (!!!fs.isEmpty())) {
+       for (String filter : fs) {
+         try {
+         filters.add(FrameworkUtil.createFilter(FilterUtils.removeMandatoryFilterToken(filter)));
+         } catch (InvalidSyntaxException ise) {
+           InvalidAttributeException iae = new InvalidAttributeException(ise);
+           throw iae;
+         }
+       }
+     }
+     return filters;
+   }
+  
+   private  String convertFiltersToString(Collection<Filter> contents, String separator) {
+     StringBuilder newContent = new StringBuilder();
+     if ((contents != null) && (!!!contents.isEmpty())) {
+       boolean beginning = true;
+       for (Filter content: contents) {
+         if (beginning)
+           newContent.append(separator);
+         newContent.append(content.toString());
+         beginning = false;
+       }
+     }
+     return newContent.toString();
+   }
+   
+   
+}
\ No newline at end of file

Added: aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/impl/ServiceDeclarationImpl.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/impl/ServiceDeclarationImpl.java?rev=1075132&view=auto
==============================================================================
--- aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/impl/ServiceDeclarationImpl.java (added)
+++ aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/impl/ServiceDeclarationImpl.java Sun Feb 27 20:20:13 2011
@@ -0,0 +1,97 @@
+/*
+ * 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.impl;
+
+import org.apache.aries.application.Content;
+import org.apache.aries.application.ServiceDeclaration;
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+
+/**
+ * this class represents the Import-Services and Export-Services
+ * in the Application.mf file
+ *
+ */
+public class ServiceDeclarationImpl implements ServiceDeclaration
+{
+  private static final String FILTER = "filter";
+  private String interfaceName;
+  private Filter filter;
+  
+  /**
+   * construct the ServiceDeclaration from the service string
+   * @param service A single service string value from the Import-Services or Export-Services header
+   * @throws InvalidSyntaxException
+   */
+  public ServiceDeclarationImpl(String service) throws InvalidSyntaxException 
+  {
+    Content content = new ContentImpl(service);
+    this.interfaceName = content.getContentName();
+    String filterString = content.getAttribute(FILTER);
+    if (filterString != null) {
+      try {
+        this.filter = FrameworkUtil.createFilter(filterString);
+      } catch (InvalidSyntaxException ise) {        
+        throw new InvalidSyntaxException("Failed to create filter for " + service, ise.getFilter(), ise.getCause());
+      }
+    }
+  }
+  
+  /* (non-Javadoc)
+ * @see org.apache.aries.application.impl.ServiceDeclaration#getInterfaceName()
+ */
+  public String getInterfaceName() 
+  {
+    return this.interfaceName;
+  }
+  
+  /* (non-Javadoc)
+ * @see org.apache.aries.application.impl.ServiceDeclaration#getFilter()
+ */
+  public Filter getFilter() 
+  {
+    return this.filter;
+  }
+  @Override
+  public int hashCode()
+  {
+    final int prime = 31;
+    int result = 1;
+    result = prime * result + ((filter == null) ? 0 : filter.hashCode());
+    result = prime * result + ((interfaceName == null) ? 0 : interfaceName.hashCode());
+    return result;
+  }
+
+  @Override
+  public boolean equals(Object obj)
+  {
+    if (this == obj) return true;
+    if (obj == null) return false;
+    if (getClass() != obj.getClass()) return false;
+    ServiceDeclarationImpl other = (ServiceDeclarationImpl) obj;
+    if (filter == null) {
+      if (other.filter != null) return false;
+    } else if (!filter.equals(other.filter)) return false;
+    if (interfaceName == null) {
+      if (other.interfaceName != null) return false;
+    } else if (!interfaceName.equals(other.interfaceName)) return false;
+    return true;
+  }
+}

Added: aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/impl/VersionRangeImpl.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/impl/VersionRangeImpl.java?rev=1075132&view=auto
==============================================================================
--- aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/impl/VersionRangeImpl.java (added)
+++ aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/impl/VersionRangeImpl.java Sun Feb 27 20:20:13 2011
@@ -0,0 +1,149 @@
+/*
+ * 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.impl;
+
+import org.apache.aries.application.VersionRange;
+import org.osgi.framework.Version;
+
+public final class VersionRangeImpl implements VersionRange {
+
+  private org.apache.aries.util.VersionRange versionRange;
+  /**
+   * 
+   * @param version   version for the verioninfo
+   */
+  public VersionRangeImpl(String version) {
+      versionRange = new org.apache.aries.util.VersionRange(version);
+  }
+
+  /**
+   * 
+   * @param version             version for the versioninfo
+   * @param exactVersion        whether this is an exact version
+   */
+  public VersionRangeImpl(String version, boolean exactVersion) {
+      versionRange = new org.apache.aries.util.VersionRange(version, exactVersion);
+  }
+
+  private VersionRangeImpl(org.apache.aries.util.VersionRange versionRange) {
+      this.versionRange = versionRange;
+  }
+  
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.aries.application.impl.VersionRange#toString()
+   */
+  @Override
+  public String toString() {
+      return versionRange.toString();
+  }
+
+  @Override
+  public int hashCode() {
+      return versionRange.hashCode();
+  }
+  
+  @Override
+  public boolean equals(Object other) {
+      boolean result = false;
+      if (this == other) {
+          result = true;
+      } else if (other instanceof VersionRangeImpl) {
+          VersionRangeImpl vr = (VersionRangeImpl) other;   
+          result = versionRange.equals(vr.versionRange);
+      }
+      return result;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.aries.application.impl.VersionRange#getExactVersion()
+   */
+  public Version getExactVersion() {
+      return versionRange.getExactVersion();
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.aries.application.impl.VersionRange#getMaximumVersion()
+   */
+  public Version getMaximumVersion() {
+      return versionRange.getMaximumVersion();
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.aries.application.impl.VersionRange#getMinimumVersion()
+   */
+  public Version getMinimumVersion() {
+      return versionRange.getMinimumVersion();
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.aries.application.impl.VersionRange#isMaximumExclusive()
+   */
+  public boolean isMaximumExclusive() {
+      return versionRange.isMaximumExclusive();
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.aries.application.impl.VersionRange#isMaximumUnbounded()
+   */
+  public boolean isMaximumUnbounded() {
+      return versionRange.isMaximumUnbounded();
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.aries.application.impl.VersionRange#isMinimumExclusive()
+   */
+  public boolean isMinimumExclusive() {
+      return versionRange.isMinimumExclusive();
+  }
+  
+  /**
+   * This method checks that the provided version matches the desired version.
+   * 
+   * @param version
+   *          the version.
+   * @return true if the version matches, false otherwise.
+   */
+  public boolean matches(Version version) {
+      return versionRange.matches(version);
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.aries.application.impl.VersionRange#isExactVersion()
+   */
+  public boolean isExactVersion() {
+      return versionRange.isExactVersion();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.aries.application.impl.VersionRange#intersect(VersionRange
+   * range)
+   */
+  public VersionRange intersect(VersionRange r) {
+      VersionRangeImpl rr = (VersionRangeImpl) r;      
+      org.apache.aries.util.VersionRange result = versionRange.intersect(rr.versionRange);
+      return (result == null) ? null : new VersionRangeImpl(result);
+  }
+
+}

Added: aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/AppConstants.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/AppConstants.java?rev=1075132&view=auto
==============================================================================
--- aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/AppConstants.java (added)
+++ aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/AppConstants.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 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.utils;
+
+
+/**
+ * Widely used constants in parsing Aries applications
+ */
+public interface AppConstants
+{
+  /** Trace group for this bundle */
+  public String TRACE_GROUP = "Aries.app.utils";
+
+
+  /** The Manifest version */
+  public static final String APPLICATION_MANIFEST_VERSION="Manifest-Version";
+  
+  /** The application scope (used to find the applications bundle repository */
+  public static final String APPLICATION_SCOPE = "Application-Scope";
+  /** The application content directive for the application manifest */
+  public static final String APPLICATION_CONTENT = "Application-Content";
+  /** The application version directive for the application manifest */
+  public static final String APPLICATION_VERSION = "Application-Version";
+  /** The application name directive for the application manifest */
+  public static final String APPLICATION_NAME = "Application-Name";
+  /** The application symbolic name directive for the application manifest */
+  public static final String APPLICATION_SYMBOLIC_NAME = "Application-SymbolicName";
+  /** The default version for applications that do not have one */
+  public static final String DEFAULT_VERSION = "0.0.0";
+  /** The name of the application manifest in the application */
+  public static final String APPLICATION_MF = "META-INF/APPLICATION.MF";
+  /** The name of the deployment manifest in the application */
+  public static final String DEPLOYMENT_MF = "META-INF/DEPLOYMENT.MF";
+  /** The name of the META-INF directory   */
+  public static final String META_INF = "META-INF";
+  /** The name of an application.xml file which will be used in processing legacy .war files */
+  public static final String APPLICATION_XML = "META-INF/application.xml";
+  /** The expected lower case suffix of a jar file */
+  public static final String LOWER_CASE_JAR_SUFFIX = ".jar";
+  /** The expected lower case suffix of a war file */
+  public static final String LOWER_CASE_WAR_SUFFIX = ".war";
+  /** The attribute used to record the deployed version of a bundle */
+  public static final String DEPLOYMENT_BUNDLE_VERSION = "deployed-version";
+  /** The name of the bundle manifest */
+  public static final String MANIFEST_MF = "META-INF/MANIFEST.MF";
+  
+  public static final String MANIFEST_VERSION="1.0";
+  /** The application import service directive for the application manifest */
+  public static final String APPLICATION_IMPORT_SERVICE = "Application-ImportService";
+  /** The application export service directive for the application manifest */
+  public static final String APPLICATION_EXPORT_SERVICE = "Application-ExportService"; 
+  /** The use-bundle entry for the application manifest. */
+  public static final String APPLICATION_USE_BUNDLE = "Use-Bundle";
+  /* The Deployed-Content header in DEPLOYMENT.MF records all the bundles
+   * to be deployed for a particular application. 
+   */
+  public static final String DEPLOYMENT_CONTENT = "Deployed-Content";
+  /** deployment.mf entry corresponding to application.mf Use-Bundle. */
+  public static final String DEPLOYMENT_USE_BUNDLE = "Deployed-Use-Bundle";
+  /** deployment.mf entry 'Import-Package' */
+  public static final String DEPLOYMENT_IMPORT_PACKAGES="Import-Package";
+  /** Bundle dependencies required by bundles listed in Deployed-Content or Deployed-Use-Bundle. */
+  public static final String DEPLOYMENT_PROVISION_BUNDLE = "Provision-Bundle";  
+  /** Blueprint managed services imported by the isolated bundles */ 
+  public static final String DEPLOYMENTSERVICE_IMPORT = "DeployedService-Import";
+  
+  public static final String PROVISON_EXCLUDE_LOCAL_REPO_SYSPROP="provision.exclude.local.repository";
+  /**
+   * Logging insert strings
+   */
+  public final static String LOG_ENTRY = "Method entry: {}, args {}";
+  public final static String LOG_EXIT = "Method exit: {}, returning {}";
+  public final static String LOG_EXCEPTION = "Caught exception";
+}

Added: aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/FilterUtils.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/FilterUtils.java?rev=1075132&view=auto
==============================================================================
--- aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/FilterUtils.java (added)
+++ aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/FilterUtils.java Sun Feb 27 20:20:13 2011
@@ -0,0 +1,63 @@
+/*
+ * 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.utils;
+
+import static org.apache.aries.application.utils.AppConstants.LOG_ENTRY;
+import static org.apache.aries.application.utils.AppConstants.LOG_EXIT;
+
+import java.util.regex.Pattern;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+public class FilterUtils
+{
+  private static final Pattern regexp = Pattern.compile("\\(mandatory:.*?\\)");
+
+  private static final  Logger logger = LoggerFactory.getLogger(FilterUtils.class);
+  /**
+   * Filters we generate may contain stanzas like (mandatory:<*symbolicname)
+   * These are for OBR, and are not OSGi friendly!!! This method removes them.
+   * 
+   * @param filter
+   * @return A filter with the mandatory stanzas removed or null if a null filter is supplied
+   */
+  public static String removeMandatoryFilterToken(String filter) {
+    logger.debug(LOG_ENTRY, "areMandatoryAttributesPresent", new Object[]{filter});
+    if(filter != null) {
+      filter = regexp.matcher(filter).replaceAll("");
+    
+      int openBraces = 0;
+      for (int i=0; openBraces < 3; i++) {
+        i = filter.indexOf('(', i);
+        if (i == -1) { 
+          break;
+        } else { 
+          openBraces++;
+        }
+      }
+      // Need to prune (& or (| off front and ) off end
+      if (openBraces < 3 && 
+          (filter.startsWith("(&") || filter.startsWith("(|"))) { 
+        filter = filter.substring(2, filter.length() - 1);
+      }
+    }
+    logger.debug(LOG_EXIT, "removeMandatoryFilterToken", filter);
+    return filter;
+  }
+}

Added: aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/ServiceDeclarationFactory.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/ServiceDeclarationFactory.java?rev=1075132&view=auto
==============================================================================
--- aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/ServiceDeclarationFactory.java (added)
+++ aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/ServiceDeclarationFactory.java Sun Feb 27 20:20:13 2011
@@ -0,0 +1,32 @@
+/*
+ * 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.utils;
+
+import org.apache.aries.application.ServiceDeclaration;
+import org.apache.aries.application.impl.ServiceDeclarationImpl;
+import org.osgi.framework.InvalidSyntaxException;
+
+public class ServiceDeclarationFactory {
+
+  public static ServiceDeclaration getServiceDeclaration (String s) throws InvalidSyntaxException 
+  { 
+    return new ServiceDeclarationImpl(s); 
+  }
+}

Added: aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/filesystem/FileSystem.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/filesystem/FileSystem.java?rev=1075132&view=auto
==============================================================================
--- aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/filesystem/FileSystem.java (added)
+++ aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/filesystem/FileSystem.java Sun Feb 27 20:20:13 2011
@@ -0,0 +1,67 @@
+/*
+ * 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.utils.filesystem;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+import org.apache.aries.application.filesystem.IDirectory;
+import org.apache.aries.application.utils.filesystem.impl.DirectoryImpl;
+import org.apache.aries.application.utils.filesystem.impl.ZipDirectory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * An abstraction of a file system. A file system can be a zip, or a directory.
+ */
+public class FileSystem {
+
+  private static final Logger _logger = LoggerFactory.getLogger("org.apache.aries.application.utils");
+
+  /**
+   * This method gets the IDirectory that represents the root of a virtual file
+   * system. The provided file can either identify a directory, or a zip file.
+   * 
+   * @param fs the zip file.
+   * @return   the root of the virtual FS.
+   */
+  public static IDirectory getFSRoot(File fs)
+  {
+    IDirectory dir = null;
+    
+    if (fs.exists()) {
+      if (fs.isDirectory()) {
+        dir = new DirectoryImpl(fs, fs);
+      } else if (fs.isFile()) {
+        try {
+          dir = new ZipDirectory(fs, fs);
+        } catch (IOException e) {
+          _logger.error ("IOException in IDirectory.getFSRoot", e);
+        }
+      }
+    }
+    else {
+      // since this method does not throw an exception but just returns null, make sure we do not lose the error
+      _logger.error("File not found in IDirectory.getFSRoot", new FileNotFoundException(fs.getPath()));
+    }
+    return dir;
+  }
+}

Added: aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/filesystem/IOUtils.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/filesystem/IOUtils.java?rev=1075132&view=auto
==============================================================================
--- aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/filesystem/IOUtils.java (added)
+++ aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/filesystem/IOUtils.java Sun Feb 27 20:20:13 2011
@@ -0,0 +1,294 @@
+/*
+ * 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.utils.filesystem;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipException;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
+
+import org.apache.aries.application.filesystem.IFile;
+import org.apache.aries.application.utils.internal.MessageUtil;
+
+public class IOUtils
+{
+  /**
+   * Copy an InputStream to an OutputStream and close the InputStream afterwards.
+   */
+  public static void copy(InputStream in, OutputStream out) throws IOException
+  {
+    try {
+      copyAndDoNotCloseInputStream(in, out);
+    }
+    finally {
+      close(in);
+    }
+  }
+  
+  /**
+   * Copy an InputStream to an OutputStream and do not close the InputStream afterwards.
+   */
+  public static void copyAndDoNotCloseInputStream(InputStream in, OutputStream out) throws IOException
+  {
+    int len;
+    byte[] b = new byte[1024];
+    while ((len = in.read(b)) != -1)
+      out.write(b,0,len);
+  }
+  
+  /**
+   * Close some xStream for good :)
+   */
+  public static void close(Closeable c)
+  {
+    try {
+      if (c != null)
+        c.close();
+    }
+    catch (IOException e) {
+      c = null;
+    }
+  }
+  
+  /**
+   * A special version of close() for ZipFiles, which don't implement Closeable.
+   * @param file the file to close. ZipFiles seem prone to file locking problems
+   * on Windows, so to aid diagnostics we throw, not swallow, any exceptions. 
+   */
+  public static void close(ZipFile file) throws IOException
+  {
+    if (file != null) file.close();
+  }
+  
+  public static OutputStream getOutputStream(File outputDir, String relativePath) throws IOException
+  {
+    int lastSeparatorIndex = relativePath.replace(File.separatorChar,'/').lastIndexOf("/");
+    String dirName = null;
+    String fileName = null;
+    
+    File outputDirectory;
+    if (lastSeparatorIndex != -1)
+    {
+      dirName = relativePath.substring(0, lastSeparatorIndex);
+      fileName = relativePath.substring(lastSeparatorIndex + 1);
+
+      outputDirectory = new File(outputDir, dirName);
+      
+      if (!!!outputDirectory.exists() && !!!outputDirectory.mkdirs())
+        throw new IOException(MessageUtil.getMessage("APPUTILS0012E", relativePath));
+    }
+    else
+    {
+      outputDirectory = outputDir;
+      fileName = relativePath;
+    }
+    
+    File outputFile = new File(outputDirectory, fileName);
+    return new FileOutputStream(outputFile);
+  }
+  
+  /**
+   * Write the given InputStream to a file given by a root directory (outputDir) and a relative directory.
+   * Necessary subdirectories will be created. This method will close the supplied InputStream.
+   */
+  public static void writeOut(File outputDir, String relativePath, InputStream content) throws IOException
+  {
+    OutputStream out = null;
+    try {
+      out = getOutputStream(outputDir, relativePath);
+      IOUtils.copy(content, out);
+    }
+    finally {
+      close(out);
+    }
+  }
+  
+  /**
+   * Write the given InputStream to a file given by a root directory (outputDir) and a relative directory.
+   * Necessary subdirectories will be created. This method will not close the supplied InputStream.
+   */
+  public static void writeOutAndDontCloseInputStream(File outputDir, String relativePath, InputStream content) throws IOException
+  {
+    OutputStream out = null;
+    try {
+      out = getOutputStream(outputDir, relativePath);
+      IOUtils.copyAndDoNotCloseInputStream(content, out);
+    }
+    finally {
+      close(out);
+    }
+  }
+  
+   /** 
+   * Zip up all contents of rootDir (recursively) into targetStream
+   */
+  @SuppressWarnings("unchecked")
+  public static void zipUp (File rootDir, OutputStream targetStream) throws IOException
+  {
+    ZipOutputStream out = null;
+    try { 
+      out = new ZipOutputStream (targetStream);
+      zipUpRecursive(out, "", rootDir, (Set<String>) Collections.EMPTY_SET);
+    } finally { 
+      close(out);
+    }
+  }
+  
+  /**
+   * Zip up all contents of rootDir (recursively) into targetFile
+   */
+  @SuppressWarnings("unchecked")
+  public static void zipUp(File rootDir, File targetFile) throws IOException
+  {
+    ZipOutputStream out = null; 
+    try {
+      out = new ZipOutputStream(new FileOutputStream(targetFile));
+      zipUpRecursive(out, "", rootDir, (Set<String>) Collections.EMPTY_SET);
+    }
+    finally {
+      close(out);
+    }
+  }
+  
+  /**
+   * Jar up all the contents of rootDir (recursively) into targetFile and add the manifest
+   */
+  public static void jarUp(File rootDir, File targetFile, Manifest manifest) throws IOException
+  {
+    JarOutputStream out = null;
+    try {
+      out = new JarOutputStream(new FileOutputStream(targetFile), manifest);
+      zipUpRecursive(out, "", rootDir, new HashSet<String>(Arrays.asList("META-INF/MANIFEST.MF")));
+    }
+    finally {
+      close(out);
+    }
+  }
+  
+  /**
+   * Helper method used by zipUp
+   */
+  private static void zipUpRecursive(ZipOutputStream out, String prefix, 
+      File directory, Set<String> filesToExclude) throws IOException
+  {
+    File[] files = directory.listFiles();
+    if (files != null) 
+    {
+      for (File f : files)
+      {        
+        String fileName; 
+        if (f.isDirectory())
+          fileName = prefix + f.getName() + "/";
+        else
+          fileName = prefix + f.getName();
+        
+        if (filesToExclude.contains(fileName))
+          continue;
+        
+        ZipEntry ze = new ZipEntry(fileName);
+        ze.setSize(f.length());
+        ze.setTime(f.lastModified());
+        out.putNextEntry(ze);
+
+        if (f.isDirectory()) 
+          zipUpRecursive(out, fileName, f, filesToExclude);
+        else 
+        {
+          IOUtils.copy(new FileInputStream(f), out);
+        }
+      }
+    }
+  }
+  
+  /**
+   * Do rm -rf
+   */
+  public static boolean deleteRecursive(File root)
+  {
+    if (!!!root.exists())
+      return false;
+    else if (root.isFile())
+      return root.delete();
+    else {
+      boolean result = true;
+      for (File f : root.listFiles())
+      {
+        result = deleteRecursive(f) && result;
+      }
+      return root.delete() && result;
+    }
+  }
+  
+  /**
+   * Unpack the zip file into the outputDir
+   * @param zip
+   * @param outputDir
+   * @return true if the zip was expanded, false if the zip was found not to be a zip
+   * @throws IOException when there are unexpected issues handling the zip files.
+   */
+  public static boolean unpackZip(IFile zip, File outputDir) throws IOException{
+    boolean success=true;
+    //unpack from fileOnDisk into bundleDir.
+    ZipInputStream zis = null;
+    try{
+      boolean isZip = false;
+      ZipEntry zipEntry = null;
+      try {
+        zis = new ZipInputStream (zip.open());
+        zipEntry = zis.getNextEntry();
+        isZip = zipEntry != null; 
+      } catch (ZipException e) { // It's not a zip - that's ok, we'll return that below. 
+        isZip = false;
+      } catch (UnsupportedOperationException e) {  // This isn't declared, but is thrown in practice
+        isZip = false;                             // It's not a zip - that's ok, we'll return that below. 
+      }
+      if(isZip){
+        do { 
+          if (!zipEntry.isDirectory()) { 
+            writeOutAndDontCloseInputStream(outputDir, zipEntry.getName(), zis);
+          }
+          zis.closeEntry();
+          zipEntry = zis.getNextEntry();
+        } while (zipEntry != null);
+      }else{
+        success=false;
+      }
+    }finally{
+      IOUtils.close(zis);
+    }
+    return success;
+  }
+  
+
+}

Added: aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/filesystem/impl/DirectoryImpl.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/filesystem/impl/DirectoryImpl.java?rev=1075132&view=auto
==============================================================================
--- aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/filesystem/impl/DirectoryImpl.java (added)
+++ aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/filesystem/impl/DirectoryImpl.java Sun Feb 27 20:20:13 2011
@@ -0,0 +1,151 @@
+/*
+ * 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.utils.filesystem.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.aries.application.filesystem.IDirectory;
+import org.apache.aries.application.filesystem.IFile;
+
+/**
+ * An IDirectory representing a java.io.File whose isDirectory method returns true.
+ */
+public class DirectoryImpl extends FileImpl implements IDirectory
+{
+  /**
+   * @param dir      the file to represent.
+   * @param rootFile the file that represents the FS root.
+   */
+  public DirectoryImpl(File dir, File rootFile)
+  {
+    super(dir, rootFile);
+  }
+
+  public IFile getFile(String name)
+  {
+    File desiredFile = new File(file, name);
+    IFile result = null;
+    
+    if (desiredFile.exists()) 
+    {
+        if(!desiredFile.isDirectory())
+          result = new FileImpl(desiredFile, rootDirFile);
+        else
+          result = new DirectoryImpl(desiredFile, rootDirFile);
+    }
+    
+    return result;
+  }
+
+  public boolean isRoot()
+  {
+    boolean result = (rootDirFile == file);
+    return result;
+  }
+
+  public List<IFile> listFiles()
+  {
+    List<IFile> files = new ArrayList<IFile>();
+    File[] filesInDir = file.listFiles();
+    if (filesInDir != null) {
+      for (File f : filesInDir) {
+        if (f.isFile()) {
+          files.add(new FileImpl(f, rootDirFile));
+        } else if (f.isDirectory()) {
+          files.add(new DirectoryImpl(f, rootDirFile));
+        }
+      }
+    }
+    return files;
+  }
+  public List<IFile> listAllFiles()
+  {
+    List<IFile> files = new ArrayList<IFile>();
+    File[] filesInDir = file.listFiles();
+    if (filesInDir != null) {
+      for (File f : filesInDir) {
+        if (f.isFile()) {
+          files.add(new FileImpl(f, rootDirFile));
+        } else if (f.isDirectory()) {
+          files.add(new DirectoryImpl(f, rootDirFile));
+          listSubDirectoryFiles(files, f);
+        }
+      }
+    }
+    return files;
+  }
+  
+  private void listSubDirectoryFiles(List<IFile> lists, File file) {
+    File[] filesInDir = file.listFiles();
+    if (filesInDir != null) {
+      for (File f : filesInDir) {
+        if (f.isFile()) {
+          lists.add(new FileImpl(f, rootDirFile));
+        } else if (f.isDirectory()) {
+          lists.add(new DirectoryImpl(f, rootDirFile));
+          listSubDirectoryFiles(lists, f);
+        }
+      }
+    }
+    
+  }
+
+  public Iterator<IFile> iterator()
+  {
+    Iterator<IFile> result = listFiles().iterator();
+    return result;
+  }
+
+  @Override
+  public IDirectory getParent()
+  {
+    IDirectory result = isRoot() ? null : super.getParent();
+    return result;
+  }
+
+  @Override
+  public IDirectory convert()
+  {
+    return this;
+  }
+
+  @Override
+  public InputStream open() throws IOException
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public long getLastModified()
+  {
+    long result = super.getLastModified();
+    for (IFile aFile : this) {
+      long tmpLastModified = aFile.getLastModified();
+      
+      if (tmpLastModified > result) result = tmpLastModified;
+    }
+    return result;
+  }
+}

Added: aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/filesystem/impl/FileImpl.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/filesystem/impl/FileImpl.java?rev=1075132&view=auto
==============================================================================
--- aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/filesystem/impl/FileImpl.java (added)
+++ aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/filesystem/impl/FileImpl.java Sun Feb 27 20:20:13 2011
@@ -0,0 +1,143 @@
+/*
+ * 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.utils.filesystem.impl;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.apache.aries.application.filesystem.IDirectory;
+import org.apache.aries.application.filesystem.IFile;
+
+/**
+ * An implementation of IFile that represents a java.io.File.
+ */
+public class FileImpl implements IFile
+{
+  
+  /** The name of the root directory of the file system */
+  protected String rootDir;
+  /** This file in the file system */
+  protected File file;
+  /** The root File in the file system */
+  protected File rootDirFile;
+  /** The name of this file in the vFS */
+  private String name;
+  
+  /**
+   * @param f        this file.
+   * @param rootFile the root of the vFS.
+   */
+  public FileImpl(File f, File rootFile)
+  {
+    file = f;
+    this.rootDirFile = rootFile;
+    rootDir = rootFile.getAbsolutePath();
+    
+    if (f == rootFile) name = "";
+    else name = file.getAbsolutePath().substring(rootDir.length() + 1);
+  }
+  
+  public IDirectory convert()
+  {
+    return null;
+  }
+
+  public long getLastModified()
+  {
+    long result = file.lastModified();
+    return result;
+  }
+
+  public String getName()
+  {
+    return name;
+  }
+
+  public IDirectory getParent()
+  {
+    IDirectory parent = new DirectoryImpl(file.getParentFile(), rootDirFile);
+    return parent;
+  }
+
+  public long getSize()
+  {
+    long size = file.length();
+    return size;
+  }
+
+  public boolean isDirectory()
+  {
+    boolean result = file.isDirectory();
+    return result;
+  }
+
+  public boolean isFile()
+  {
+    boolean result = file.isFile();
+    return result;
+  }
+
+  public InputStream open() throws IOException
+  {
+    InputStream is = new FileInputStream(file);
+    return is;
+  }
+
+  public IDirectory getRoot()
+  {
+    IDirectory root = new DirectoryImpl(rootDirFile, rootDirFile);
+    return root;
+  }
+
+  public URL toURL() throws MalformedURLException
+  {
+    URL result = file.toURI().toURL();
+    return result;
+  }
+
+  @Override
+  public boolean equals(Object obj)
+  {
+    if (obj == null) return false;
+    if (obj == this) return true;
+    
+    if (obj.getClass() == getClass()) {
+      return file.equals(((FileImpl)obj).file);
+    }
+    
+    return false;
+  }
+
+  @Override
+  public int hashCode()
+  {
+    return file.hashCode();
+  }
+  
+  @Override
+  public String toString()
+  {
+    return file.getAbsolutePath();
+  }
+}
\ No newline at end of file

Added: aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/filesystem/impl/ZipDirectory.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/filesystem/impl/ZipDirectory.java?rev=1075132&view=auto
==============================================================================
--- aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/filesystem/impl/ZipDirectory.java (added)
+++ aries/tags/application-0.3/application-utils/src/main/java/org/apache/aries/application/utils/filesystem/impl/ZipDirectory.java Sun Feb 27 20:20:13 2011
@@ -0,0 +1,256 @@
+/*
+ * 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.utils.filesystem.impl;
+
+import java.io.File;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import org.apache.aries.application.filesystem.IDirectory;
+import org.apache.aries.application.filesystem.IFile;
+
+/**
+ * A directory in the zip.
+ */
+public class ZipDirectory extends ZipFileImpl implements IDirectory
+{
+  /** The root of the zip FS. */
+  private ZipDirectory root;
+  
+  /**
+   * Constructs a directory in the zip.
+   * 
+   * @param zip1   the zip file.
+   * @param entry1 the entry in the zip representing this dir.
+   * @param parent the parent directory.
+   */
+  public ZipDirectory(File zip1, ZipEntry entry1, ZipDirectory parent)
+  {
+    super(zip1, entry1, parent);
+  }
+
+  /**
+   * This constructor creates the root of the zip.
+   * @param file
+   * @param fs
+   * @throws MalformedURLException 
+   */
+  public ZipDirectory(File file, File fs) throws MalformedURLException
+  {
+    super(file, fs);
+    root = this;
+  }
+
+  public IFile getFile(String name)
+  {
+    IFile result = null;
+    
+    String entryName = isRoot() ? name : getName() + "/" + name;
+    
+    ZipEntry entryFile = getEntry(entryName);
+    
+    if (entryFile != null) {
+      if (!!!entryFile.isDirectory()) {
+        result = new ZipFileImpl(zip, entryFile, buildParent(entryFile));
+      } else {
+        result = new ZipDirectory(zip, entryFile, buildParent(entryFile));
+      }
+    }
+    return result;
+  }
+
+  /**
+   * This method builds the parent directory hierarchy for a file.
+   * @param foundEntry
+   * @return the parent of the entry.
+   */
+  private ZipDirectory buildParent(ZipEntry foundEntry)
+  {
+    ZipDirectory result = this;
+    
+    String name = foundEntry.getName();
+    
+    name = name.substring(getName().length());
+    
+    String[] paths = name.split("/");
+    
+    StringBuilder baseBuilderCrapThingToGetRoundFindBugs = new StringBuilder(getName());
+    
+    if (!!!isRoot()) baseBuilderCrapThingToGetRoundFindBugs.append('/');
+    // Build 'result' as a chain of ZipDirectories. This will only work if java.util.ZipFile recognises every 
+    // directory in the chain as being a ZipEntry in its own right. 
+    outer: if (paths != null && paths.length > 1) {
+      for (int i = 0; i < paths.length - 1; i++) {
+        String path = paths[i];
+        baseBuilderCrapThingToGetRoundFindBugs.append(path);
+        ZipEntry dirEntry = getEntry(baseBuilderCrapThingToGetRoundFindBugs.toString());
+        if (dirEntry == null) { 
+          result = this;
+          break outer;
+        }
+        result = new ZipDirectory(zip, dirEntry, result);
+        baseBuilderCrapThingToGetRoundFindBugs.append('/');
+      }
+    }
+    return result;
+  }
+
+  public boolean isRoot()
+  {
+    boolean result = (root == this);
+    return result;
+  }
+
+  public List<IFile> listFiles()
+  {
+    List<IFile> files = new ArrayList<IFile>();
+    
+    ZipFile z = openZipFile();
+    Enumeration<? extends ZipEntry> entries = z.entries();
+    
+    while (entries.hasMoreElements()) {
+      ZipEntry possibleEntry = entries.nextElement();
+      
+      if (isInDir(possibleEntry)) {
+        if (possibleEntry.isDirectory()) {
+          files.add(new ZipDirectory(zip, possibleEntry, this));
+        } else {
+          files.add(new ZipFileImpl(zip, possibleEntry, this));
+        }
+      }
+    }
+    closeZipFile(z);
+    return files;
+  }
+
+  public List<IFile> listAllFiles()
+  {
+    List<IFile> files = new ArrayList<IFile>();
+
+    ZipFile z = openZipFile();
+    Enumeration<? extends ZipEntry> entries = z.entries();
+
+    while (entries.hasMoreElements()) {
+      ZipEntry possibleEntry = entries.nextElement();
+      if (possibleEntry.isDirectory()) {
+        files.add(new ZipDirectory(zip, possibleEntry, this));
+      } else {
+        files.add(new ZipFileImpl(zip, possibleEntry, this));
+      }
+      
+    }
+    closeZipFile(z);
+    return files;
+  }
+  /**
+   * This method works out if the provided entry is inside this directory. It
+   * returns false if it is not, or if it is in a sub-directory.
+   * 
+   * @param possibleEntry
+   * @return true if it is in this directory.
+   */
+  private boolean isInDir(ZipEntry possibleEntry)
+  {
+    boolean result;
+    String name = possibleEntry.getName();
+    String parentDir = getName();
+    if (name.endsWith("/")) name = name.substring(0, name.length() - 1);
+    result = (name.startsWith(parentDir) && !!!name.equals(parentDir) && name.substring(parentDir.length() + 1).indexOf('/') == -1);
+    return result;
+  }
+
+  public Iterator<IFile> iterator()
+  {
+    Iterator<IFile> result = listFiles().iterator();
+    return result;
+  }
+
+  @Override
+  public IDirectory convert()
+  {
+    return this;
+  }
+
+  @Override
+  public IDirectory getParent()
+  {
+    IDirectory result = isRoot() ? null : super.getParent();
+    return result;
+  }
+
+  @Override
+  public boolean isDirectory()
+  {
+    return true;
+  }
+
+  @Override
+  public boolean isFile()
+  {
+    return false;
+  }
+
+  @Override
+  public InputStream open() 
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public IDirectory getRoot()
+  {
+    return root;
+  }
+  
+  // Although we only delegate to our super class if we removed this Findbugs
+  // would correctly point out that we add fields in this class, but do not
+  // take them into account for the equals method. In fact this is not a problem
+  // we do not care about the root when doing an equality check, but by including
+  // an equals or hashCode in here we can clearly document that we did this
+  // on purpose. Hence this comment.
+  @Override
+  public boolean equals(Object other)
+  {
+    return super.equals(other);
+  }
+  
+  @Override
+  public int hashCode()
+  {
+    return super.hashCode();
+  }
+  
+  private ZipEntry getEntry(String entryName){
+    ZipFile z = openZipFile();
+    ZipEntry entryFile = null;
+    
+    if (z != null) {
+      entryFile = z.getEntry(entryName);
+      closeZipFile(z);
+    }
+    return entryFile;
+  }
+}
\ No newline at end of file