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 19:53:06 UTC
svn commit: r1075118 [6/7] - in /aries/tags/application-0.2-incubating: ./
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/ appli...
Added: aries/tags/application-0.2-incubating/application-utils/src/main/java/org/apache/aries/application/utils/manifest/ManifestDefaultsInjector.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.2-incubating/application-utils/src/main/java/org/apache/aries/application/utils/manifest/ManifestDefaultsInjector.java?rev=1075118&view=auto
==============================================================================
--- aries/tags/application-0.2-incubating/application-utils/src/main/java/org/apache/aries/application/utils/manifest/ManifestDefaultsInjector.java (added)
+++ aries/tags/application-0.2-incubating/application-utils/src/main/java/org/apache/aries/application/utils/manifest/ManifestDefaultsInjector.java Sun Feb 27 18:52:58 2011
@@ -0,0 +1,281 @@
+/*
+ * 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.manifest;
+
+import java.io.File;
+import java.util.Map;
+import java.util.jar.Manifest;
+
+import org.apache.aries.application.filesystem.IDirectory;
+import org.apache.aries.application.filesystem.IFile;
+import org.apache.aries.application.utils.AppConstants;
+import org.apache.aries.application.utils.filesystem.FileSystem;
+import org.osgi.framework.Version;
+
+public class ManifestDefaultsInjector
+{
+ /**
+ * Quick adapter to update a Manifest, using content of a Zip File.
+ * <p>
+ * This is really a wrapper of updateManifest(Manifest,String,IDirectory), with the
+ * IDirectory being being created from the Zip File. This method avoids other Bundles
+ * requiring IDirectory solely for calling updateManifest.
+ * <p>
+ * @param mf Manifest to be updated
+ * @param appName The name to use for this app, if the name contains
+ * a '_' char then the portion after the '_' is used, if possible, as
+ * the application version.
+ * @param zip Content to use for application.
+ * @return true if manifest modified, false otherwise.
+ */
+ public static boolean updateManifest(Manifest mf, String appName, File zip){
+ IDirectory appPathIDir = FileSystem.getFSRoot(zip);
+ boolean result = updateManifest(mf, appName, appPathIDir);
+ return result;
+ }
+
+ /**
+ * Tests the supplied manifest for the presence of expected
+ * attributes, and where missing, adds them, and defaults
+ * their values appropriately.
+ *
+ * @param mf The manifest to test & update if needed.
+ * @param appName The name to use for this app, if the name contains
+ * a '_' char then the portion after the '_' is used, if possible, as
+ * the application version.
+ * @param appDir The IDirectory to scan to build application content
+ * property
+ * @return true if manifest modified, false otherwise.
+ */
+ public static boolean updateManifest(Manifest mf, String appName, IDirectory appDir){
+ Map<String, String> props = ManifestProcessor.readManifestIntoMap(mf);
+ String extracted[] = extractAppNameAndVersionFromNameIfPossible(appName);
+ String name = extracted[0];
+ String version = extracted[1];
+
+ boolean updated = false;
+ updated |= defaultAppSymbolicName(mf, props, name);
+ updated |= defaultAppName(mf, props, name);
+ updated |= defaultVersion(mf, props, version);
+ updated |= defaultAppScope(mf, props, name, version);
+ updated |= defaultAppContent(mf, props, appDir);
+
+ return updated;
+ }
+
+ /**
+ * Takes a compound name_version string, and returns the Name & Version information.
+ * <p>
+ * @param name Contains name data related to this app. Expected format is name_version
+ * @return Array of String, index 0 is appName, index 1 is Version.
+ * <br> Name will be the appname retrieved from the 'name' argument, Version will be the
+ * version if found and valid, otherwise will be defaulted.
+ */
+ private static String[] extractAppNameAndVersionFromNameIfPossible(String name){
+ String retval[] = new String[2];
+ String appName = name;
+ String defaultedVersion;
+
+ int index = name.indexOf('_');
+
+ if (index != -1) {
+ appName = name.substring(0, index);
+ defaultedVersion = name.substring(index + 1);
+
+ try {
+ new Version(defaultedVersion);
+ } catch (IllegalArgumentException e) {
+ // this is not an error condition
+ defaultedVersion = AppConstants.DEFAULT_VERSION;
+ }
+ } else {
+ defaultedVersion = AppConstants.DEFAULT_VERSION;
+ }
+
+ retval[0] = appName;
+ retval[1] = defaultedVersion;
+
+ return retval;
+ }
+
+ /**
+ * Sets the app symbolic name into the manifest, if not already present.
+ *
+ * @param mf manifest to update
+ * @param props parsed manifest used to test if already present.
+ * @param appName used for name if missing
+ * @return true if manifest is modified, false otherwise.
+ */
+ private static boolean defaultAppSymbolicName(Manifest mf, Map<String, String> props, String appName){
+ boolean updated = false;
+ if (!props.containsKey(AppConstants.APPLICATION_SYMBOLIC_NAME)) {
+ mf.getMainAttributes().putValue(AppConstants.APPLICATION_SYMBOLIC_NAME, appName);
+ updated = true;
+ }
+ return updated;
+ }
+
+ /**
+ * Sets the app name into the manifest, if not already present.
+ *
+ * @param mf manifest to update
+ * @param props parsed manifest used to test if already present.
+ * @param appName used for name if missing
+ * @return true if manifest is modified, false otherwise.
+ */
+ private static boolean defaultAppName(Manifest mf, Map<String, String> props, String appName){
+ boolean updated = false;
+ if (!props.containsKey(AppConstants.APPLICATION_NAME)) {
+ mf.getMainAttributes().putValue(AppConstants.APPLICATION_NAME, appName);
+ updated = true;
+ }
+ return updated;
+ }
+
+ /**
+ * Sets the app version into the manifest, if not already present.
+ *
+ * @param mf manifest to update
+ * @param props parsed manifest used to test if already present.
+ * @param appVersion used for version if missing
+ * @return true if manifest is modified, false otherwise.
+ */
+ private static boolean defaultVersion(Manifest mf, Map<String, String> props, String appVersion){
+ boolean updated = false;
+ if (!props.containsKey(AppConstants.APPLICATION_VERSION)) {
+ mf.getMainAttributes().putValue(AppConstants.APPLICATION_VERSION, appVersion);
+ updated = true;
+ }
+ return updated;
+ }
+
+ /**
+ * Sets the app scope into the manifest, if not already present.
+ *
+ * @param mf manifest to update
+ * @param props parsed manifest used to test if already present.
+ * @param name used to build appScope if app symbolic name not set.
+ * @param version used to build appScope if app version missing.
+ * @return true if manifest is modified, false otherwise.
+ */
+ private static boolean defaultAppScope(Manifest mf, Map<String, String> props, String name, String version){
+ boolean updated = false;
+ if (!props.containsKey(AppConstants.APPLICATION_SCOPE)) {
+
+ String appSymbolicName;
+ if (props.containsKey(AppConstants.APPLICATION_SYMBOLIC_NAME)) {
+ appSymbolicName = props.get(AppConstants.APPLICATION_SYMBOLIC_NAME);
+ } else {
+ appSymbolicName = name;
+ }
+
+ String appVersion;
+ if (props.containsKey(AppConstants.APPLICATION_VERSION)) {
+ appVersion = props.get(AppConstants.APPLICATION_VERSION);
+ } else {
+ appVersion = version;
+ }
+
+ String appScope = appSymbolicName + '_' + appVersion;
+ mf.getMainAttributes().putValue(AppConstants.APPLICATION_SCOPE, appScope);
+ updated = true;
+ }
+ return updated;
+ }
+
+ /**
+ * Sets the app content into the manifest, if not already present.
+ * <p>
+ * This method will NOT set the appcontent if it is unable to build it.
+ * This is important, as the absence of appcontent is used by some callers
+ * to test if a manifest contains all required content.
+ *
+ * @param mf manifest to update
+ * @param props parsed manifest used to test if already present.
+ * @param appDir used to build app content if missing.
+ * @return true if manifest is modified, false otherwise.
+ */
+ private static boolean defaultAppContent(Manifest mf, Map<String, String> props, IDirectory appDir){
+ boolean updated = false;
+ if (!props.containsKey(AppConstants.APPLICATION_CONTENT)) {
+ String appContent = calculateAppContent(appDir);
+ if (appContent != null) {
+ mf.getMainAttributes().putValue(AppConstants.APPLICATION_CONTENT, appContent);
+ updated = true;
+ }
+ }
+ return updated;
+ }
+
+ /**
+ * Processes an IDirectory to find targets that require adding to the application content attrib.
+ *
+ * @param appDir The IDirectory to scan
+ * @return AppContent string, or null if no content was found.
+ */
+ private static String calculateAppContent(IDirectory appDir){
+ StringBuilder builder = new StringBuilder();
+ for (IFile file : appDir) {
+ processPossibleBundle(file, builder);
+ }
+ String returnVal = null;
+ if (builder.length() > 0) {
+ builder.deleteCharAt(builder.length() - 1);
+ returnVal = builder.toString();
+ }
+ return returnVal;
+ }
+
+ /**
+ * This method works out if the given IFile represents an OSGi bundle and if
+ * it is then we append a matching rule to the String builder.
+ *
+ * @param file to file to check.
+ * @param builder the builder to append to.
+ */
+ private static void processPossibleBundle(IFile file, StringBuilder builder)
+ {
+ if (file.isDirectory() || (file.isFile() && (file.getName().endsWith(".jar") || file.getName().endsWith(".war")))) {
+ BundleManifest bundleMf = BundleManifest.fromBundle(file);
+ if (bundleMf != null) {
+ String manifestVersion = bundleMf.getManifestVersion();
+ String name = bundleMf.getSymbolicName();
+ String version = bundleMf.getVersion().toString();
+
+ // if the bundle manifest version is 2 AND a symbolic name is specified we have a valid bundle
+ if ("2".equals(manifestVersion) && name != null) {
+
+ builder.append(name);
+
+ // bundle version is not a required manifest header
+ if (version != null) {
+ builder.append(";version=\"[");
+ builder.append(version);
+ builder.append(',');
+ builder.append(version);
+ builder.append("]\"");
+ }
+
+ // the last comma will be removed once all content has been added
+ builder.append(",");
+ }
+ }
+ }
+ }
+}
Added: aries/tags/application-0.2-incubating/application-utils/src/main/java/org/apache/aries/application/utils/manifest/ManifestHeaderProcessor.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.2-incubating/application-utils/src/main/java/org/apache/aries/application/utils/manifest/ManifestHeaderProcessor.java?rev=1075118&view=auto
==============================================================================
--- aries/tags/application-0.2-incubating/application-utils/src/main/java/org/apache/aries/application/utils/manifest/ManifestHeaderProcessor.java (added)
+++ aries/tags/application-0.2-incubating/application-utils/src/main/java/org/apache/aries/application/utils/manifest/ManifestHeaderProcessor.java Sun Feb 27 18:52:58 2011
@@ -0,0 +1,694 @@
+/*
+ * 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.manifest;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.aries.application.VersionRange;
+import org.apache.aries.application.impl.VersionRangeImpl;
+import org.apache.aries.application.utils.internal.MessageUtil;
+import org.osgi.framework.Constants;
+
+
+public class ManifestHeaderProcessor
+{
+ public static final String NESTED_FILTER_ATTRIBUTE = "org.apache.aries.application.filter.attribute";
+ private static final Pattern FILTER_ATTR = Pattern.compile("(\\(!)?\\((.*?)([<>]?=)(.*?)\\)\\)?");
+ private static final String LESS_EQ_OP = "<=";
+ private static final String GREATER_EQ_OP = ">=";
+
+ /**
+ * A simple class to associate two types.
+ *
+ * @param <N> The type for the 'Name'
+ * @param <V> The type for the 'Value'
+ */
+ public static class NameValuePair<N,V>{
+ private N name;
+ private V value;
+ public NameValuePair(N name, V value)
+ {
+ this.name = name;
+ this.value = value;
+ }
+ public N getName()
+ {
+ return name;
+ }
+ public void setName(N name)
+ {
+ this.name = name;
+ }
+ public V getValue()
+ {
+ return value;
+ }
+ public void setValue(V value)
+ {
+ this.value = value;
+ }
+ @Override
+ public String toString(){
+ return "{"+name.toString()+"::"+value.toString()+"}";
+ }
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ result = prime * result + ((value == null) ? 0 : value.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;
+ final NameValuePair<?, ?> other = (NameValuePair<?, ?>) obj;
+ if (name == null) {
+ if (other.name != null) return false;
+ } else if (!name.equals(other.name)) return false;
+ if (value == null) {
+ if (other.value != null) return false;
+ } else if (!value.equals(other.value)) return false;
+ return true;
+ }
+ }
+
+ /**
+ * Intended to provide a standard way to add Name/Value's to
+ * aggregations of Name/Value's.
+ *
+ * @param <N> Type of 'Name'
+ * @param <V> Type of 'Value'
+ */
+ public static interface NameValueCollection<N,V>{
+ /**
+ * Add this Name & Value to the collection.
+ * @param n
+ * @param v
+ */
+ public void addToCollection(N n,V v);
+ }
+
+ /**
+ * Map of Name -> Value.
+ *
+ * @param <N> Type of 'Name'
+ * @param <V> Type of 'Value'
+ */
+ public static class NameValueMap<N,V> extends HashMap<N,V> implements NameValueCollection<N,V>, Map<N,V>{
+
+ public void addToCollection(N n,V v){
+ this.put(n,v);
+ }
+ @Override
+ public String toString(){
+ StringBuffer sb = new StringBuffer();
+ sb.append("{");
+ boolean first=true;
+ for(Map.Entry<N, V> entry : this.entrySet()){
+ if(!first)sb.append(",");
+ first=false;
+ sb.append(entry.getKey()+"->"+entry.getValue());
+ }
+ sb.append("}");
+ return sb.toString();
+ }
+ }
+
+ /**
+ * List of Name/Value
+ *
+ * @param <N> Type of 'Name'
+ * @param <V> Type of 'Value'
+ */
+ public static class NameValueList<N,V> extends ArrayList<NameValuePair<N,V>> implements NameValueCollection<N,V>, List<NameValuePair<N,V>>{
+
+ public void addToCollection(N n,V v){
+ this.add(new NameValuePair<N,V>(n,v));
+ }
+ @Override
+ public String toString(){
+ StringBuffer sb = new StringBuffer();
+ sb.append("{");
+ boolean first = true;
+ for(NameValuePair<N, V> nvp : this){
+ if(!first)sb.append(",");
+ first=false;
+ sb.append(nvp.toString());
+ }
+ sb.append("}");
+ return sb.toString();
+ }
+ }
+
+ /**
+ *
+ * Splits a delimiter separated string, tolerating presence of non separator commas
+ * within double quoted segments.
+ *
+ * Eg.
+ * com.ibm.ws.eba.helloWorldService;version="[1.0.0, 1.0.0]" &
+ * com.ibm.ws.eba.helloWorldService;version="1.0.0"
+ * com.ibm.ws.eba.helloWorld;version="2";bundle-version="[2,30)"
+ * com.acme.foo;weirdAttr="one;two;three";weirdDir:="1;2;3"
+ * @param value the value to be split
+ * @param delimiter the delimiter string such as ',' etc.
+ * @return List<String> the components of the split String in a list
+ */
+ public static List<String> split(String value, String delimiter)
+ {
+ List<String> result = new ArrayList<String>();
+ if (value != null) {
+ String[] packages = value.split(delimiter);
+
+ for (int i = 0; i < packages.length; ) {
+ String tmp = packages[i++].trim();
+ // if there is a odd number of " in a string, we need to append
+ while (count(tmp, "\"") % 2 != 0) {
+ // check to see if we need to append the next package[i++]
+ if (i<packages.length)
+ tmp = tmp + delimiter + packages[i++].trim();
+ else
+ // oops. The double quotes are not paired up. We have reached to the end of the string.
+ throw new IllegalArgumentException(MessageUtil.getMessage("APPUTILS0008E",tmp));
+ }
+
+ result.add(tmp);
+
+ }
+ }
+ return result;
+ }
+
+ /**
+ * count the number of characters in a string
+ * @param parent The string to be searched
+ * @param subString The substring to be found
+ * @return the number of occurrence of the subString
+ */
+ private static int count(String parent, String subString) {
+
+ int count = 0 ;
+ int i = parent.indexOf(subString);
+ while (i > -1) {
+ if (parent.length() >= i+1)
+ parent = parent.substring(i+1);
+ count ++;
+ i = parent.indexOf(subString);
+ }
+ return count;
+ }
+ /**
+ * Internal method to parse headers with the format<p>
+ * [Name](;[Name])*(;[attribute-name]=[attribute-value])*<br>
+ * Eg.<br>
+ * rumplestiltskin;thing=value;other=something<br>
+ * littleredridinghood
+ * bundle1;bundle2;other=things
+ * bundle1;bundle2
+ *
+ * @param s data to parse
+ * @return a list of NameValuePair, with the Name being the name component,
+ * and the Value being a NameValueMap of key->value mappings.
+ */
+ private static List<NameValuePair<String, NameValueMap<String, String>>> genericNameWithNameValuePairProcess(String s){
+ String name;
+ NameValueMap<String,String> params = null;
+ List<NameValuePair<String, NameValueMap<String, String>>> nameValues = new ArrayList<NameValuePair<String, NameValueMap<String, String>>>();
+ List<String> pkgs = new ArrayList<String>();
+ int index = s.indexOf(";");
+ if(index==-1){
+ name = s;
+ params = new NameValueMap<String, String>();
+ pkgs.add(name);
+ }else{
+ name = s.substring(0,index).trim();
+ String tail = s.substring(index+1).trim();
+
+ pkgs.add(name); // add the first package
+ StringBuilder parameters = new StringBuilder();
+
+
+ // take into consideration of multiple packages separated by ';'
+ // while they share the same attributes or directives
+ List<String> tailParts = split(tail, ";");
+ boolean firstParameter =false;
+
+ for (String part : tailParts) {
+ // if it is not a parameter and no parameter appears in front of it, it must a package
+ if (!!!(part.contains("="))) {
+ // Need to make sure no parameter appears before the package, otherwise ignore this string
+ // as this syntax is invalid
+ if (!!!(firstParameter))
+ pkgs.add(part);
+ } else {
+ if (!!!(firstParameter))
+ firstParameter = true;
+
+ parameters.append(part + ";");
+ }
+ }
+
+ if (parameters.length() != 0) {
+ //remove the final ';' if there is one
+ if (parameters.toString().endsWith(";")) {
+
+ parameters = parameters.deleteCharAt(parameters.length() -1);
+ }
+
+ params = genericNameValueProcess(parameters.toString());
+ }
+
+ }
+ for (String pkg : pkgs) {
+ nameValues.add(new NameValuePair<String, NameValueMap<String, String>>(pkg,params));
+ }
+
+ return nameValues;
+
+ }
+
+ /**
+ * Internal method to parse headers with the format<p>
+ * [attribute-name]=[attribute-value](;[attribute-name]=[attribute-value])*<br>
+ * Eg.<br>
+ * thing=value;other=something<br>
+ * <p>
+ * Note. Directives (name:=value) are represented in the map with name suffixed by ':'
+ *
+ * @param s data to parse
+ * @return a NameValueMap, with attribute-name -> attribute-value.
+ */
+ private static NameValueMap<String,String> genericNameValueProcess(String s){
+ NameValueMap<String,String> params = new NameValueMap<String,String>();
+ List<String> parameters = split(s, ";");
+ for(String parameter : parameters) {
+ List<String> parts = split(parameter,"=");
+ // do a check, otherwise we might get NPE
+ if (parts.size() ==2) {
+ String second = parts.get(1).trim();
+ if (second.startsWith("\"") && second.endsWith("\""))
+ second = second.substring(1,second.length()-1);
+ params.put(parts.get(0).trim(), second);
+ }
+ }
+
+ return params;
+ }
+
+ /**
+ * Processes an import/export style header.. <p>
+ * pkg1;attrib=value;attrib=value,pkg2;attrib=value,pkg3;attrib=value
+ *
+ * @param out The collection to add each package name + attrib map to.
+ * @param s The data to parse
+ */
+ private static void genericImportExportProcess(NameValueCollection<String, NameValueMap<String,String>>out, String s){
+ List<String> packages = split(s, ",");
+ for(String pkg : packages){
+ List<NameValuePair<String, NameValueMap<String, String>>> ps = genericNameWithNameValuePairProcess(pkg);
+ for (NameValuePair<String, NameValueMap<String, String>> p : ps) {
+ out.addToCollection(p.getName(), p.getValue());
+ }
+ }
+ }
+
+ /**
+ * Parse an export style header.<p>
+ * pkg1;attrib=value;attrib=value,pkg2;attrib=value,pkg3;attrib=value2
+ * <p>
+ * Result is returned as a list, as export does allow duplicate package exports.
+ *
+ * @param list The data to parse.
+ * @return List of NameValuePairs, where each Name in the list is an exported package,
+ * with its associated Value being a NameValueMap of any attributes declared.
+ */
+ public static List<NameValuePair<String, NameValueMap<String, String>>> parseExportString(String s){
+ NameValueList<String, NameValueMap<String, String>> retval = new NameValueList<String, NameValueMap<String, String>>();
+ genericImportExportProcess(retval, s);
+ return retval;
+ }
+
+ /**
+ * Parse an export style header in a list.<p>
+ * pkg1;attrib=value;attrib=value
+ * pkg2;attrib=value
+ * pkg3;attrib=value2
+ * <p>
+ * Result is returned as a list, as export does allow duplicate package exports.
+ *
+ * @param list The data to parse.
+ * @return List of NameValuePairs, where each Name in the list is an exported package,
+ * with its associated Value being a NameValueMap of any attributes declared.
+ */
+ public static List<NameValuePair<String, NameValueMap<String, String>>> parseExportList(List<String> list){
+ NameValueList<String, NameValueMap<String, String>> retval = new NameValueList<String, NameValueMap<String, String>>();
+ for(String pkg : list){
+ List<NameValuePair<String, NameValueMap<String, String>>> ps = genericNameWithNameValuePairProcess(pkg);
+ for (NameValuePair<String, NameValueMap<String, String>> p : ps) {
+ retval.addToCollection(p.getName(), p.getValue());
+ }
+ }
+ return retval;
+ }
+
+ /**
+ * Parse an import style header.<p>
+ * pkg1;attrib=value;attrib=value,pkg2;attrib=value,pkg3;attrib=value
+ * <p>
+ * Result is returned as a set, as import does not allow duplicate package imports.
+ *
+ * @param s The data to parse.
+ * @return Map of NameValuePairs, where each Key in the Map is an imported package,
+ * with its associated Value being a NameValueMap of any attributes declared.
+ */
+ public static Map<String, NameValueMap<String, String>> parseImportString(String s){
+ NameValueMap<String, NameValueMap<String, String>> retval = new NameValueMap<String, NameValueMap<String, String>>();
+ genericImportExportProcess(retval, s);
+ return retval;
+ }
+
+ /**
+ * Parse a bundle symbolic name.<p>
+ * bundlesymbolicname;attrib=value;attrib=value
+ * <p>
+ *
+ * @param s The data to parse.
+ * @return NameValuePair with Name being the BundleSymbolicName,
+ * and Value being any attribs declared for the name.
+ */
+ public static NameValuePair<String, NameValueMap<String, String>> parseBundleSymbolicName(String s){
+ return genericNameWithNameValuePairProcess(s).get(0); // should just return the first one
+ }
+
+ /**
+ * Parse a version range..
+ *
+ * @param s
+ * @return VersionRange object.
+ * @throws IllegalArgumentException if the String could not be parsed as a VersionRange
+ */
+ public static VersionRange parseVersionRange(String s) throws IllegalArgumentException{
+ return new VersionRangeImpl(s);
+ }
+
+ /**
+ * Parse a version range and indicate if the version is an exact version
+ *
+ * @param s
+ * @param exactVersion
+ * @return VersionRange object.
+ * @throws IllegalArgumentException if the String could not be parsed as a VersionRange
+ */
+ public static VersionRange parseVersionRange(String s, boolean exactVersion) throws IllegalArgumentException{
+ return new VersionRangeImpl(s, exactVersion);
+ }
+
+ /**
+ * Generate a filter from a set of attributes. This filter will be suitable
+ * for presentation to OBR This means that, due to the way OBR works, it
+ * will include a stanza of the form, (mandatory:<*mandatoryAttribute)
+ * Filter strings generated by this method will therefore tend to break the
+ * standard OSGi Filter class. The OBR stanza can be stripped out later if
+ * required.
+ *
+ * @param attribs
+ * @return filter string
+ */
+ public static String generateFilter(Map<String, String> attribs) {
+ StringBuilder filter = new StringBuilder("(&");
+ boolean realAttrib = false;
+ StringBuffer realAttribs = new StringBuffer();
+
+ if (attribs == null) {
+ attribs = new HashMap<String, String>();
+ }
+
+ for (Map.Entry<String, String> attrib : attribs.entrySet()) {
+ String attribName = attrib.getKey();
+
+ if (attribName.endsWith(":")) {
+ // skip all directives. It is used to affect the attribs on the
+ // filter xml.
+ } else if ((Constants.VERSION_ATTRIBUTE.equals(attribName))
+ || (Constants.BUNDLE_VERSION_ATTRIBUTE.equals(attribName))) {
+ // version and bundle-version attrib requires special
+ // conversion.
+ realAttrib = true;
+
+ VersionRange vr = ManifestHeaderProcessor
+ .parseVersionRange(attrib.getValue());
+
+ filter.append("(" + attribName + ">=" + vr.getMinimumVersion());
+
+ if (vr.getMaximumVersion() != null) {
+ filter.append(")(" + attribName + "<=");
+ filter.append(vr.getMaximumVersion());
+ }
+
+ if (vr.getMaximumVersion() != null && vr.isMinimumExclusive()) {
+ filter.append(")(!(" + attribName + "=");
+ filter.append(vr.getMinimumVersion());
+ filter.append(")");
+ }
+
+ if (vr.getMaximumVersion() != null && vr.isMaximumExclusive()) {
+ filter.append(")(!(" + attribName + "=");
+ filter.append(vr.getMaximumVersion());
+ filter.append(")");
+ }
+ filter.append(")");
+
+ } else if (NESTED_FILTER_ATTRIBUTE.equals(attribName)) {
+ // Filters go in whole, no formatting needed
+ realAttrib = true;
+ filter.append(attrib.getValue());
+
+ } else if (Constants.OBJECTCLASS.equals(attribName)) {
+ realAttrib = true;
+ // objectClass has a "," separated list of interfaces
+ String[] values = attrib.getValue().split(",");
+ for (String s : values)
+ filter.append("(" + Constants.OBJECTCLASS + "=" + s + ")");
+
+ } else {
+ // attribName was not version..
+ realAttrib = true;
+
+ filter.append("(" + attribName + "=" + attrib.getValue() + ")");
+ // store all attributes in order to build up the mandatory
+ // filter and separate them with ", "
+ // skip bundle-symbolic-name in the mandatory directive query
+ if (!!!Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE
+ .equals(attribName)) {
+ realAttribs.append(attribName);
+ realAttribs.append(", ");
+ }
+ }
+ }
+ /*
+ * The following is how OBR makes mandatory attributes work, we require
+ * that the set of mandatory attributes on the export is a subset of (or
+ * equal to) the set of the attributes we supply.
+ */
+
+ if (realAttribs.length() > 0) {
+ String attribStr = (realAttribs.toString()).trim();
+ // remove the final ,
+ if ((attribStr.length() > 0) && (attribStr.endsWith(","))) {
+ attribStr = attribStr.substring(0, attribStr.length() - 1);
+ }
+ // build the mandatory filter, e.g.(mandatory:<*company, local)
+ filter.append("(" + Constants.MANDATORY_DIRECTIVE + ":" + "<*"
+ + attribStr + ")");
+ }
+
+ // Prune (& off the front and ) off end
+ String filterString = filter.toString();
+ int openBraces = 0;
+ for (int i = 0; openBraces < 3; i++) {
+ i = filterString.indexOf('(', i);
+ if (i == -1) {
+ break;
+ } else {
+ openBraces++;
+ }
+ }
+ if (openBraces < 3 && filterString.length() > 2) {
+ filter.delete(0, 2);
+ } else {
+ filter.append(")");
+ }
+
+ String result = "";
+ if (realAttrib != false) {
+ result = filter.toString();
+ }
+ return result;
+ }
+
+ /**
+ * Generate a filter from a set of attributes. This filter will be suitable
+ * for presentation to OBR. This means that, due to the way OBR works, it will
+ * include a stanza of the form, (mandatory:<*mandatoryAttribute) Filter
+ * strings generated by this method will therefore tend to break the standard
+ * OSGi Filter class. The OBR stanza can be stripped out later if required.
+ *
+ * We may wish to consider relocating this method since VersionRange has its
+ * own top level class.
+ *
+ * @param type
+ * @param name
+ * @param attribs
+ * @return filter string
+ */
+ public static String generateFilter(String type, String name,
+ Map<String, String> attribs) {
+ StringBuffer filter = new StringBuffer();
+ String result;
+ // shortcut for the simple case with no attribs.
+
+ if (attribs == null || attribs.isEmpty())
+ filter.append("(" + type + "=" + name + ")");
+ else {
+ // process all the attribs passed.
+ // find out whether there are attributes on the filter
+
+ filter.append("(&(" + type + "=" + name + ")");
+
+ String filterString = generateFilter(attribs);
+
+ int start = 0;
+ int end = filterString.length();
+ if (filterString.startsWith("(&")) {
+ start = 2;
+ end--;
+ }
+
+ if ("".equals(filterString)) {
+ filter.delete(0, 2);
+ } else {
+ filter.append(filterString, start, end);
+ filter.append(")");
+ }
+ }
+
+ result = filter.toString();
+
+ return result;
+ }
+
+ private static Map<String, String> parseFilterList(String filter) {
+
+ Map<String, String> result = new HashMap<String, String>();
+ Set<String> negatedVersions = new HashSet<String>();
+ Set<String> negatedBundleVersions = new HashSet<String>();
+
+ String lowerVersion = null;
+ String upperVersion = null;
+ String lowerBundleVersion = null;
+ String upperBundleVersion = null;
+
+ Matcher m = FILTER_ATTR.matcher(filter);
+ while (m.find()) {
+ boolean negation = m.group(1) != null;
+ String attr = m.group(2);
+ String op = m.group(3);
+ String value = m.group(4);
+
+ if (Constants.VERSION_ATTRIBUTE.equals(attr)) {
+ if (negation) {
+ negatedVersions.add(value);
+ } else {
+ if (GREATER_EQ_OP.equals(op))
+ lowerVersion = value;
+ else if (LESS_EQ_OP.equals(op))
+ upperVersion = value;
+ else
+ throw new IllegalArgumentException();
+ }
+ } else if (Constants.BUNDLE_VERSION_ATTRIBUTE.equals(attr)) {
+ // bundle-version is like version, but may be specified at the
+ // same time
+ // therefore we have similar code with separate variables
+ if (negation) {
+ negatedBundleVersions.add(value);
+ } else {
+ if (GREATER_EQ_OP.equals(op))
+ lowerBundleVersion = value;
+ else if (LESS_EQ_OP.equals(op))
+ upperBundleVersion = value;
+ else
+ throw new IllegalArgumentException();
+ }
+ } else {
+ result.put(attr, value);
+ }
+ }
+
+ if (lowerVersion != null) {
+ StringBuilder versionAttr = new StringBuilder(lowerVersion);
+ if (upperVersion != null) {
+ versionAttr.append(",").append(upperVersion).insert(0,
+ negatedVersions.contains(lowerVersion) ? '(' : '[').append(
+ negatedVersions.contains(upperVersion) ? ')' : ']');
+ }
+
+ result.put(Constants.VERSION_ATTRIBUTE, versionAttr.toString());
+ }
+ // Do it again for bundle-version
+ if (lowerBundleVersion != null) {
+ StringBuilder versionAttr = new StringBuilder(lowerBundleVersion);
+ if (upperBundleVersion != null) {
+ versionAttr.append(",").append(upperBundleVersion).insert(0,
+ negatedBundleVersions.contains(lowerBundleVersion) ? '(' : '[')
+ .append(
+ negatedBundleVersions.contains(upperBundleVersion) ? ')' : ']');
+ }
+
+ result.put(Constants.BUNDLE_VERSION_ATTRIBUTE, versionAttr.toString());
+ }
+
+ return result;
+ }
+
+ public static Map<String,String> parseFilter(String filter)
+ {
+ Map<String,String> result;
+ if (filter.startsWith("(&")) {
+ result = parseFilterList(filter.substring(2, filter.length()-1));
+ } else {
+ result = parseFilterList(filter);
+ }
+ return result;
+ }
+}
+
Added: aries/tags/application-0.2-incubating/application-utils/src/main/java/org/apache/aries/application/utils/manifest/ManifestProcessor.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.2-incubating/application-utils/src/main/java/org/apache/aries/application/utils/manifest/ManifestProcessor.java?rev=1075118&view=auto
==============================================================================
--- aries/tags/application-0.2-incubating/application-utils/src/main/java/org/apache/aries/application/utils/manifest/ManifestProcessor.java (added)
+++ aries/tags/application-0.2-incubating/application-utils/src/main/java/org/apache/aries/application/utils/manifest/ManifestProcessor.java Sun Feb 27 18:52:58 2011
@@ -0,0 +1,201 @@
+/*
+ * 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.manifest;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+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.filesystem.IDirectory;
+import org.apache.aries.application.filesystem.IFile;
+
+/**
+ * This class contains utilities for parsing manifests. It provides methods to
+ * parse the manifest, read a manifest into a map and to split an manifest
+ * entry that follows the Import-Package syntax.
+ */
+public class ManifestProcessor
+{
+ /**
+ * 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.
+ */
+ public static 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;
+ }
+
+ /**
+ * This method parses the manifest using a custom manifest parsing routine.
+ * This means that we can avoid the 76 byte line length in a manifest providing
+ * a better developer experience.
+ *
+ * @param in the input stream to read the manifest from.
+ * @return the parsed manifest
+ * @throws IOException
+ */
+ public static Manifest parseManifest(InputStream in) throws IOException
+ {
+ Manifest man = new Manifest();
+
+ // I'm assuming that we use UTF-8 here, but the jar spec doesn't say.
+ BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
+
+ String line;
+ StringBuilder attribute = null;
+
+ String namedAttribute = null;
+
+ do {
+ line = reader.readLine();
+
+ // if we get a blank line skip to the next one
+ if (line != null && line.trim().length() == 0) continue;
+ if (line != null && line.charAt(0) == ' ' && attribute != null) {
+ // we have a continuation line, so add to the builder, ignoring the
+ // first character
+ attribute.append(line.trim());
+ } else if (attribute == null) {
+ attribute = new StringBuilder(line.trim());
+ } else if (attribute != null) {
+ // We have fully parsed an attribute
+ int index = attribute.indexOf(":");
+ String attributeName = attribute.substring(0, index).trim();
+ // TODO cope with index + 1 being after the end of attribute
+ String attributeValue = attribute.substring(index + 1).trim();
+
+ if ("Name".equals(attributeName)) {
+ man.getEntries().put(attributeValue, new Attributes());
+ namedAttribute = attributeValue;
+ } else {
+ if (namedAttribute == null) {
+ man.getMainAttributes().put(new Attributes.Name(attributeName), attributeValue);
+ } else {
+ man.getAttributes(namedAttribute).put(new Attributes.Name(attributeName), attributeValue);
+ }
+ }
+
+ if (line != null) attribute = new StringBuilder(line.trim());
+ }
+ } while (line != null);
+
+ return man;
+ }
+
+ /**
+ * Obtain a manifest from an IDirectory.
+ *
+ * @param appDir
+ * @param manifestName the name of manifest
+ * @return Manifest, or null if none found.
+ * @throws IOException
+ */
+ public static Manifest obtainManifestFromAppDir(IDirectory appDir, String manifestName) throws IOException{
+ IFile manifestFile = appDir.getFile(manifestName);
+ Manifest man = null;
+ if (manifestFile != null) {
+ man = parseManifest(manifestFile.open());
+ }
+ return man;
+ }
+
+
+ /**
+ *
+ * Splits a delimiter separated string, tolerating presence of non separator commas
+ * within double quoted segments.
+ *
+ * Eg.
+ * com.ibm.ws.eba.helloWorldService;version="[1.0.0, 1.0.0]" &
+ * com.ibm.ws.eba.helloWorldService;version="1.0.0"
+ * com.ibm.ws.eba.helloWorld;version="2";bundle-version="[2,30)"
+ * com.acme.foo;weirdAttr="one;two;three";weirdDir:="1;2;3"
+ * @param value the value to be split
+ * @param delimiter the delimiter string such as ',' etc.
+ * @return List<String> the components of the split String in a list
+ */
+ public static List<String> split(String value, String delimiter)
+ {
+
+ List<String> result = new ArrayList<String>();
+ if (value != null) {
+ String[] packages = value.split(delimiter);
+
+ for (int i = 0; i < packages.length; ) {
+ String tmp = packages[i++].trim();
+ // if there is a odd number of " in a string, we need to append
+ while (count(tmp, "\"") % 2 == 1) {
+ // check to see if we need to append the next package[i++]
+ tmp = tmp + delimiter + packages[i++].trim();
+ }
+
+ result.add(tmp);
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * count the number of characters in a string
+ * @param parent The string to be searched
+ * @param subString The substring to be found
+ * @return the number of occurrence of the subString
+ */
+ private static int count(String parent, String subString) {
+
+ int count = 0 ;
+ int i = parent.indexOf(subString);
+ while (i > -1) {
+ if (parent.length() >= i+1)
+ parent = parent.substring(i+1);
+ count ++;
+ i = parent.indexOf(subString);
+ }
+ return count;
+ }
+}
Added: aries/tags/application-0.2-incubating/application-utils/src/main/resources/OSGI-INF/blueprint/app-utils.xml
URL: http://svn.apache.org/viewvc/aries/tags/application-0.2-incubating/application-utils/src/main/resources/OSGI-INF/blueprint/app-utils.xml?rev=1075118&view=auto
==============================================================================
--- aries/tags/application-0.2-incubating/application-utils/src/main/resources/OSGI-INF/blueprint/app-utils.xml (added)
+++ aries/tags/application-0.2-incubating/application-utils/src/main/resources/OSGI-INF/blueprint/app-utils.xml Sun Feb 27 18:52:58 2011
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+ <bean id="applicationMf-factory" class="org.apache.aries.application.impl.ApplicationMetadataFactoryImpl" />
+ <service interface="org.apache.aries.application.ApplicationMetadataFactory" ref="applicationMf-factory" />
+
+ <bean id="deploymentMf-factory" class="org.apache.aries.application.impl.DeploymentMetadataFactoryImpl" />
+ <service interface="org.apache.aries.application.DeploymentMetadataFactory" ref="deploymentMf-factory" />
+
+</blueprint>
Added: aries/tags/application-0.2-incubating/application-utils/src/main/resources/org/apache/aries/application/utils/messages/APPUTILSmessages.properties
URL: http://svn.apache.org/viewvc/aries/tags/application-0.2-incubating/application-utils/src/main/resources/org/apache/aries/application/utils/messages/APPUTILSmessages.properties?rev=1075118&view=auto
==============================================================================
--- aries/tags/application-0.2-incubating/application-utils/src/main/resources/org/apache/aries/application/utils/messages/APPUTILSmessages.properties (added)
+++ aries/tags/application-0.2-incubating/application-utils/src/main/resources/org/apache/aries/application/utils/messages/APPUTILSmessages.properties Sun Feb 27 18:52:58 2011
@@ -0,0 +1,22 @@
+#
+# 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.
+#
+APPUTILS0004E=APPUTILS0004E: Unable to create ContentImpl object based on content: {0}.
+APPUTILS0007E=APPUTILS0007E: The path {0} does not denote a valid file.
+APPUTILS0008E=APPUTILS0008E: Unable to parse the string, because one of the quotations marks (") is missing: {0}.
+APPUTILS0012E=APPUTILS0012E: Unable to create temporary output directory for file {0}.
Added: aries/tags/application-0.2-incubating/application-utils/src/test/java/org/apache/aries/application/impl/ApplicationMetadataImplTest.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.2-incubating/application-utils/src/test/java/org/apache/aries/application/impl/ApplicationMetadataImplTest.java?rev=1075118&view=auto
==============================================================================
--- aries/tags/application-0.2-incubating/application-utils/src/test/java/org/apache/aries/application/impl/ApplicationMetadataImplTest.java (added)
+++ aries/tags/application-0.2-incubating/application-utils/src/test/java/org/apache/aries/application/impl/ApplicationMetadataImplTest.java Sun Feb 27 18:52:58 2011
@@ -0,0 +1,40 @@
+/*
+ * 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 junit.framework.Assert;
+
+import org.apache.aries.application.ApplicationMetadata;
+import org.apache.aries.application.ApplicationMetadataFactory;
+import org.apache.aries.application.impl.ApplicationMetadataFactoryImpl;
+import org.junit.Test;
+
+public class ApplicationMetadataImplTest
+{
+ @Test
+ public void testBasicMetadataCreation() throws IOException
+ {
+ ApplicationMetadataFactory manager = new ApplicationMetadataFactoryImpl();
+ ApplicationMetadata app = manager.parseApplicationMetadata(getClass().getResourceAsStream("/META-INF/APPLICATION.MF"));
+
+ Assert.assertEquals("Travel Reservation", app.getApplicationName());
+ }
+}
Added: aries/tags/application-0.2-incubating/application-utils/src/test/java/org/apache/aries/application/impl/DeploymentContentImplTest.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.2-incubating/application-utils/src/test/java/org/apache/aries/application/impl/DeploymentContentImplTest.java?rev=1075118&view=auto
==============================================================================
--- aries/tags/application-0.2-incubating/application-utils/src/test/java/org/apache/aries/application/impl/DeploymentContentImplTest.java (added)
+++ aries/tags/application-0.2-incubating/application-utils/src/test/java/org/apache/aries/application/impl/DeploymentContentImplTest.java Sun Feb 27 18:52:58 2011
@@ -0,0 +1,65 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.aries.application.VersionRange;
+import org.junit.Test;
+import org.osgi.framework.Version;
+
+public class DeploymentContentImplTest {
+
+ @Test
+ public void testDeploymentContent001() throws Exception {
+ DeploymentContentImpl dc = new DeploymentContentImpl("com.travel.reservation.web;deployed-version=\"1.1.0\"");
+ assertEquals("1.1.0", dc.getAttribute("deployed-version"));
+ VersionRange vi = dc.getVersion();
+ assertTrue(vi.isExactVersion());
+ assertEquals(new Version("1.1.0"), dc.getExactVersion());
+ assertEquals("com.travel.reservation.web", dc.getContentName());
+ assertEquals("{deployed-version->1.1.0}", dc.getNameValueMap().toString());
+ }
+
+ @Test
+ public void testDeploymentContent002() throws Exception {
+ DeploymentContentImpl dc = new DeploymentContentImpl("com.travel.reservation.business;deployed-version=2.0");
+ assertEquals("2.0", dc.getAttribute("deployed-version"));
+ VersionRange vi = dc.getVersion();
+ assertTrue(vi.isExactVersion());
+ assertEquals(new Version("2.0"), dc.getExactVersion());
+ assertEquals("com.travel.reservation.business", dc.getContentName());
+ assertEquals("{deployed-version->2.0}", dc.getNameValueMap().toString());
+ }
+
+
+ @Test
+ public void testDeploymentContent003() throws Exception {
+ DeploymentContentImpl dc = new DeploymentContentImpl("com.travel.reservation.data;deployed-version=2.1.1");
+ assertEquals("2.1.1", dc.getAttribute("deployed-version"));
+ VersionRange vi = dc.getVersion();
+ assertTrue(vi.isExactVersion());
+ assertEquals(new Version("2.1.1"), dc.getExactVersion());
+ assertEquals("com.travel.reservation.data", dc.getContentName());
+ assertEquals("{deployed-version->2.1.1}", dc.getNameValueMap().toString());
+ }
+}
+
Added: aries/tags/application-0.2-incubating/application-utils/src/test/java/org/apache/aries/application/impl/VersionRangeTest.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.2-incubating/application-utils/src/test/java/org/apache/aries/application/impl/VersionRangeTest.java?rev=1075118&view=auto
==============================================================================
--- aries/tags/application-0.2-incubating/application-utils/src/test/java/org/apache/aries/application/impl/VersionRangeTest.java (added)
+++ aries/tags/application-0.2-incubating/application-utils/src/test/java/org/apache/aries/application/impl/VersionRangeTest.java Sun Feb 27 18:52:58 2011
@@ -0,0 +1,296 @@
+/*
+ * 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 static org.junit.Assert.*;
+
+import org.apache.aries.application.VersionRange;
+import org.junit.Test;
+import org.osgi.framework.Version;
+
+public class VersionRangeTest
+{
+ /**
+ * Test the version range created correctly
+ * @throws Exception
+ */
+
+ @Test
+ public void testVersionRange() throws Exception {
+ String version1 = "[1.2.3, 4.5.6]";
+ String version2="(1, 2]";
+ String version3="[2,4)";
+ String version4="(1,2)";
+ String version5="2";
+ String version6 = "2.3";
+ String version7="[1.2.3.q, 2.3.4.p)";
+ String version8="1.2.2.5";
+ String version9="a.b.c";
+ String version10=null;
+ String version11="";
+ String version12="\"[1.2.3, 4.5.6]\"";
+
+ VersionRange vr = new VersionRangeImpl(version1);
+ assertEquals("The value is wrong", "1.2.3", vr.getMinimumVersion().toString());
+ assertFalse("The value is wrong", vr.isMinimumExclusive());
+ assertEquals("The value is wrong", "4.5.6", vr.getMaximumVersion().toString());
+ assertFalse("The value is wrong", vr.isMaximumExclusive());
+
+ vr = new VersionRangeImpl(version2);
+ assertEquals("The value is wrong", "1.0.0", vr.getMinimumVersion().toString());
+ assertTrue("The value is wrong", vr.isMinimumExclusive());
+ assertEquals("The value is wrong", "2.0.0", vr.getMaximumVersion().toString());
+ assertFalse("The value is wrong", vr.isMaximumExclusive());
+
+ vr = new VersionRangeImpl(version3);
+
+ assertEquals("The value is wrong", "2.0.0", vr.getMinimumVersion().toString());
+ assertFalse("The value is wrong", vr.isMinimumExclusive());
+ assertEquals("The value is wrong", "4.0.0", vr.getMaximumVersion().toString());
+ assertTrue("The value is wrong", vr.isMaximumExclusive());
+
+ vr = new VersionRangeImpl(version4);
+
+ assertEquals("The value is wrong", "1.0.0", vr.getMinimumVersion().toString());
+ assertTrue("The value is wrong", vr.isMinimumExclusive());
+ assertEquals("The value is wrong", "2.0.0", vr.getMaximumVersion().toString());
+ assertTrue("The value is wrong", vr.isMaximumExclusive());
+
+ vr = new VersionRangeImpl(version5);
+ assertEquals("The value is wrong", "2.0.0", vr.getMinimumVersion().toString());
+ assertFalse("The value is wrong", vr.isMinimumExclusive());
+ assertNull("The value is wrong", vr.getMaximumVersion());
+ assertFalse("The value is wrong", vr.isMaximumExclusive());
+
+ vr = new VersionRangeImpl(version6);
+ assertEquals("The value is wrong", "2.3.0", vr.getMinimumVersion().toString());
+ assertFalse("The value is wrong", vr.isMinimumExclusive());
+ assertNull("The value is wrong", vr.getMaximumVersion());
+ assertFalse("The value is wrong", vr.isMaximumExclusive());
+
+ vr = new VersionRangeImpl(version7);
+ assertEquals("The value is wrong", "1.2.3.q", vr.getMinimumVersion().toString());
+ assertFalse("The value is wrong", vr.isMinimumExclusive());
+ assertEquals("The value is wrong", "2.3.4.p", vr.getMaximumVersion().toString());
+ assertTrue("The value is wrong", vr.isMaximumExclusive());
+
+ vr = new VersionRangeImpl(version8);
+ assertEquals("The value is wrong", "1.2.2.5", vr.getMinimumVersion().toString());
+ assertFalse("The value is wrong", vr.isMinimumExclusive());
+ assertNull("The value is wrong", vr.getMaximumVersion());
+ assertFalse("The value is wrong", vr.isMaximumExclusive());
+ boolean exception = false;
+ try {
+ vr = new VersionRangeImpl(version9);
+ } catch (Exception e){
+ exception = true;
+ }
+
+ assertTrue("The value is wrong", exception);
+ boolean exceptionNull = false;
+ try {
+ vr = new VersionRangeImpl(version10);
+ } catch (Exception e){
+ exceptionNull = true;
+ }
+ assertTrue("The value is wrong", exceptionNull);
+ // empty version should be defaulted to >=0.0.0
+ vr = new VersionRangeImpl(version11);
+ assertEquals("The value is wrong", "0.0.0", vr.getMinimumVersion().toString());
+ assertFalse("The value is wrong", vr.isMinimumExclusive());
+ assertNull("The value is wrong", vr.getMaximumVersion());
+ assertFalse("The value is wrong", vr.isMaximumExclusive());
+
+ vr = new VersionRangeImpl(version12);
+ assertEquals("The value is wrong", "1.2.3", vr.getMinimumVersion().toString());
+ assertFalse("The value is wrong", vr.isMinimumExclusive());
+ assertEquals("The value is wrong", "4.5.6", vr.getMaximumVersion().toString());
+ assertFalse("The value is wrong", vr.isMaximumExclusive());
+ }
+
+ @Test
+ public void testInvalidVersions() throws Exception
+ {
+ try {
+ new VersionRangeImpl("a");
+ assertTrue("Should have thrown an exception", false);
+ } catch (IllegalArgumentException e) {
+ }
+
+ try {
+ new VersionRangeImpl("[1.0.0,1.0.1]", true);
+ assertTrue("Should have thrown an exception", false);
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ @Test
+ public void testExactVersion() throws Exception
+ {
+ VersionRange vr;
+ try {
+ vr = new VersionRangeImpl("[1.0.0, 2.0.0]", true);
+ fail("from 1 to 2 not excludsive is not an exact range");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ vr = new VersionRangeImpl("[1.0.0, 1.0.0]", true);
+ assertTrue(vr.isExactVersion());
+
+ try {
+ vr = new VersionRangeImpl("(1.0.0, 1.0.0]", true);
+ fail("from 1 (not including 1) to 1, is not valid");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ vr = new VersionRangeImpl("[1.0.0, 1.0.0)", true);
+ fail("sfrom 1 to 1 (not including 1), is not valid");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ vr = new VersionRangeImpl("1.0.0", true);
+ assertTrue(vr.isExactVersion());
+
+ vr = new VersionRangeImpl("1.0.0", false);
+ assertFalse(vr.isExactVersion());
+
+ vr = new VersionRangeImpl("[1.0.0, 2.0.0]");
+ assertFalse(vr.isExactVersion());
+
+ vr = new VersionRangeImpl("[1.0.0, 1.0.0]");
+ assertTrue(vr.isExactVersion());
+
+ vr = new VersionRangeImpl("1.0.0", true);
+ assertEquals(new Version("1.0.0"), vr.getMinimumVersion());
+ assertTrue(vr.isExactVersion());
+
+ vr = new VersionRangeImpl("1.0.0", false);
+ assertEquals(new Version("1.0.0"), vr.getMinimumVersion());
+ assertNull(vr.getMaximumVersion());
+ assertFalse(vr.isExactVersion());
+
+ // don't throw any silly exceptions
+ vr = new VersionRangeImpl("[1.0.0,2.0.0)", false);
+ assertFalse(vr.isExactVersion());
+
+ vr = new VersionRangeImpl("[1.0.0, 2.0.0]");
+ assertFalse(vr.isExactVersion());
+
+ vr = new VersionRangeImpl("[1.0.0, 1.0.0]");
+ assertTrue(vr.isExactVersion());
+
+ }
+
+ @Test
+ public void testMatches()
+ {
+ VersionRange vr = new VersionRangeImpl("[1.0.0, 2.0.0]");
+
+ assertFalse(vr.matches(new Version(0,9,0)));
+ assertFalse(vr.matches(new Version(2,1,0)));
+ assertTrue(vr.matches(new Version(2,0,0)));
+ assertTrue(vr.matches(new Version(1,0,0)));
+ assertTrue(vr.matches(new Version(1,5,0)));
+
+ vr = new VersionRangeImpl("[1.0.0, 2.0.0)");
+
+ assertFalse(vr.matches(new Version(0,9,0)));
+ assertFalse(vr.matches(new Version(2,1,0)));
+ assertFalse(vr.matches(new Version(2,0,0)));
+ assertTrue(vr.matches(new Version(1,0,0)));
+ assertTrue(vr.matches(new Version(1,5,0)));
+
+ vr = new VersionRangeImpl("(1.0.0, 2.0.0)");
+
+ assertFalse(vr.matches(new Version(0,9,0)));
+ assertFalse(vr.matches(new Version(2,1,0)));
+ assertFalse(vr.matches(new Version(2,0,0)));
+ assertFalse(vr.matches(new Version(1,0,0)));
+ assertTrue(vr.matches(new Version(1,5,0)));
+
+ vr = new VersionRangeImpl("[1.0.0, 1.0.0]");
+ assertFalse(vr.matches(new Version(0,9,0)));
+ assertFalse(vr.matches(new Version(2,0,0)));
+ assertTrue(vr.matches(new Version(1,0,0)));
+ assertFalse(vr.matches(new Version(1,5,0)));
+ assertFalse(vr.matches(new Version(1,9,9)));
+ }
+
+ @Test
+ public void testIntersectVersionRange_Valid1()
+ {
+ VersionRange v1 = new VersionRangeImpl("[1.0.0,3.0.0]");
+ VersionRange v2 = new VersionRangeImpl("[2.0.0,3.0.0)");
+ VersionRange result = v1.intersect(v2);
+ assertNotNull(result);
+ assertEquals("[2.0.0,3.0.0)", result.toString());
+ }
+
+ @Test
+ public void testIntersectVersionRange_Valid2()
+ {
+ VersionRange v1 = new VersionRangeImpl("[1.0.0,3.0.0)");
+ VersionRange v2 = new VersionRangeImpl("(2.0.0,3.0.0]");
+ VersionRange result = v1.intersect(v2);
+ assertNotNull(result);
+ assertEquals("(2.0.0,3.0.0)", result.toString());
+ }
+
+ @Test
+ public void testIntersectVersionRange_Valid3()
+ {
+ VersionRange v1 = new VersionRangeImpl("[2.0.0,2.0.0]");
+ VersionRange v2 = new VersionRangeImpl("[1.0.0,3.0.0]");
+ VersionRange result = v1.intersect(v2);
+ assertNotNull(result);
+ assertEquals("[2.0.0,2.0.0]", result.toString());
+ }
+
+ @Test
+ public void testIntersectVersionRange_Invalid1()
+ {
+ VersionRange v1 = new VersionRangeImpl("[1.0.0,2.0.0]");
+ VersionRange v2 = new VersionRangeImpl("(2.0.0,3.0.0]");
+ VersionRange result = v1.intersect(v2);
+ assertNull(result);
+ }
+
+ @Test
+ public void testIntersectVersionRange_Invalid2()
+ {
+ VersionRange v1 = new VersionRangeImpl("[1.0.0,2.0.0)");
+ VersionRange v2 = new VersionRangeImpl("[2.0.0,3.0.0]");
+ VersionRange result = v1.intersect(v2);
+ assertNull(result);
+ }
+
+ @Test
+ public void testIntersectVersionRange_Invalid3()
+ {
+ VersionRange v1 = new VersionRangeImpl("[1.0.0,1.0.0]");
+ VersionRange v2 = new VersionRangeImpl("[2.0.0,2.0.0]");
+ VersionRange result = v1.intersect(v2);
+ assertNull(result);
+ }
+
+}
\ No newline at end of file
Added: aries/tags/application-0.2-incubating/application-utils/src/test/java/org/apache/aries/application/utils/filesystem/FileSystemTest.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.2-incubating/application-utils/src/test/java/org/apache/aries/application/utils/filesystem/FileSystemTest.java?rev=1075118&view=auto
==============================================================================
--- aries/tags/application-0.2-incubating/application-utils/src/test/java/org/apache/aries/application/utils/filesystem/FileSystemTest.java (added)
+++ aries/tags/application-0.2-incubating/application-utils/src/test/java/org/apache/aries/application/utils/filesystem/FileSystemTest.java Sun Feb 27 18:52:58 2011
@@ -0,0 +1,280 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Iterator;
+import java.util.List;
+import java.util.jar.Manifest;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import org.apache.aries.application.filesystem.IDirectory;
+import org.apache.aries.application.filesystem.IFile;
+import org.apache.aries.application.utils.AppConstants;
+import org.apache.aries.unittest.junit.Assert;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+
+/**
+ * This class contains tests for the virtual file system.
+ */
+public class FileSystemTest
+{
+ /**
+ * Make sure we correctly understand the content of the application when the
+ * application is an exploded directory. This test just checks that the
+ * root directory returns the expected information.
+ *
+ * @throws IOException
+ */
+ @Test(expected=UnsupportedOperationException.class)
+ public void basicRootDirTestsWithFiles() throws IOException
+ {
+ File baseDir = new File("../src/test/resources/app1");
+ File manifest = new File(baseDir, AppConstants.APPLICATION_MF);
+ IDirectory dir = FileSystem.getFSRoot(baseDir);
+
+ runBasicRootDirTests(dir, baseDir.length(), manifest.lastModified());
+ }
+
+ /**
+ * Make sure we correctly understand the directory structure for exploded
+ * directories.
+ *
+ * @throws IOException
+ */
+ @Test
+ public void basicDirTestsWithFiles() throws IOException
+ {
+ File baseDir = new File("../src/test/resources/app1");
+ IDirectory dir = FileSystem.getFSRoot(baseDir);
+
+ File desiredFile = new File(baseDir, AppConstants.APPLICATION_MF);
+
+ runBasicDirTest(dir, desiredFile.length(), desiredFile.lastModified());
+ }
+
+ /**
+ * Make sure we correctly understand the content of the application when the
+ * application is a zip. This test just checks that the
+ * root directory returns the expected information.
+ *
+ * @throws IOException
+ */
+ @Test(expected=UnsupportedOperationException.class)
+ public void basicRootDirTestsWithZip() throws IOException
+ {
+ File baseDir = new File("fileSystemTest/app2.zip");
+ IDirectory dir = FileSystem.getFSRoot(baseDir);
+
+ runBasicRootDirTests(dir, baseDir.length(), baseDir.lastModified());
+ }
+
+ /**
+ * Make sure we correctly understand the directory structure for zips.
+ *
+ * @throws IOException
+ */
+ @Test
+ public void basicDirTestsWithZip() throws IOException
+ {
+ File baseDir = new File("fileSystemTest/app2.zip");
+ IDirectory dir = FileSystem.getFSRoot(baseDir);
+
+ File desiredFile = new File(new File("../src/test/resources/app1"), AppConstants.APPLICATION_MF);
+
+ runBasicDirTest(dir, desiredFile.length(), desiredFile.lastModified());
+ }
+
+ /**
+ * Zip up the app1 directory to create a zippped version before running any
+ * tests.
+ *
+ * @throws IOException
+ */
+ @BeforeClass
+ public static void makeZip() throws IOException
+ {
+ File zipFile = new File("fileSystemTest/app2.zip");
+ zipFile.getParentFile().mkdirs();
+ ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFile));
+
+ int index = new File("../src/test/resources/app1").getAbsolutePath().length();
+
+ writeEnties(out, new File("../src/test/resources/app1"), index);
+
+ out.close();
+ }
+
+ /**
+ * Make sure the test zip is deleted afterwards.
+ */
+ @AfterClass
+ public static void destroyZip()
+ {
+ new File("fileSystemTest/app2.zip").delete();
+ new File("fileSystemTest").delete();
+ }
+
+ /**
+ * This method writes the given directory into the provided zip output stream.
+ * It removes the first <code>index</code> bytes from the absolute path name
+ * when building the zip.
+ *
+ * @param zos the zip output stream to use
+ * @param f the directory to write into the zip.
+ * @param index how much of the file name to chop off.
+ * @throws IOException
+ */
+ public static void writeEnties(ZipOutputStream zos, File f, int index) throws IOException {
+ File[] files = f.listFiles();
+
+ if (files != null) {
+ for (File file : files) {
+ String fileName = file.getAbsolutePath().substring(index + 1);
+
+ // Bug 1954: replace any '\' characters with '/' - required by ZipEntry
+ fileName = fileName.replace('\\', '/');
+
+ if (file.isDirectory()) fileName = fileName + "/";
+
+ ZipEntry ze = new ZipEntry(fileName);
+ ze.setSize(file.length());
+ ze.setTime(file.lastModified());
+ zos.putNextEntry(ze);
+
+ if (file.isFile()) {
+ InputStream is = new FileInputStream(file);
+ byte[] buffer = new byte[(int)file.length()];
+ int len = is.read(buffer);
+ zos.write(buffer, 0, len);
+ is.close(); // Bug 1594
+ }
+
+ zos.closeEntry();
+
+ if (file.isDirectory()) {
+ writeEnties(zos, file, index);
+ }
+ }
+ }
+ }
+
+ /**
+ * This method makes sure that the data is correctly understood from disk. It
+ * is called for both the file and zip versions of the test to ensure we have
+ * consistent results.
+ *
+ * @param dir The IDirectory for the root of the vFS.
+ * @param len The size of the file.
+ * @param time The time the file was last updated.
+ * @throws IOException
+ */
+ public void runBasicRootDirTests(IDirectory dir, long len, long time) throws IOException
+ {
+ assertEquals("The root file system name is not correct", "", dir.getName());
+ assertEquals("The size of the file is not correct", len, dir.getSize());
+
+ // This assertion just isn't working on Hudson as of build #79
+ // assertEquals("The last modified time of the file is not correct", time, dir.getLastModified());
+
+ assertNull("I managed to get a parent of a root", dir.getParent());
+ assertTrue("The root dir does not know it is a dir", dir.isDirectory());
+ assertFalse("The root dir has an identity crisis and thinks it is a file", dir.isFile());
+
+ dir.open();
+ }
+
+ /**
+ * This method makes sure that the data is correctly understood from disk. It
+ * is called for both the file and zip versions of the test to ensure we have
+ * consistent results.
+ *
+ * @param dir The IDirectory for the root of the vFS.
+ * @param len The size of the file.
+ * @param time The time the file was last updated.
+ * @throws IOException
+ */
+ public void runBasicDirTest(IDirectory dir, long len, long time) throws IOException
+ {
+ assertNull("for some reason our fake app has a fake blueprint file.", dir.getFile("OSGI-INF/blueprint/aries.xml"));
+
+ IFile file = dir.getFile(AppConstants.APPLICATION_MF);
+
+ assertNotNull("we could not find the application manifest", file);
+
+ assertEquals(AppConstants.APPLICATION_MF, file.getName().replace('\\', '/'));
+ assertTrue("The last update time is not within 2 seconds of the expected value. Expected: " + time + " Actual: " + file.getLastModified(), Math.abs(time - file.getLastModified()) < 2000);
+ assertEquals(len, file.getSize());
+ assertEquals("META-INF", file.getParent().getName());
+ assertFalse(file.isDirectory());
+ assertTrue(file.isFile());
+
+ List<IFile> files = dir.listFiles();
+ Iterator<IFile> it = files.iterator();
+ while (it.hasNext()) {
+ IFile f = it.next();
+ if (f.getName().equalsIgnoreCase(".svn")) {
+ it.remove();
+ }
+ }
+
+ assertEquals(1, files.size());
+
+ IFile metaInf = files.get(0);
+
+ assertTrue(metaInf.isDirectory());
+ assertEquals("META-INF", metaInf.getName());
+ assertNotNull(metaInf.convert());
+
+ for (IFile aFile : dir) {
+ if (!aFile.getName().equalsIgnoreCase(".svn")) {
+ assertTrue(aFile.isDirectory());
+ assertEquals("META-INF", aFile.getName());
+ assertNotNull(aFile.convert());
+ }
+ }
+
+ InputStream is = file.open();
+
+ Manifest man = new Manifest(is);
+ //remember to close the input stream after use
+ is.close();
+ assertEquals("com.travel.reservation", man.getMainAttributes().getValue("Application-SymbolicName"));
+
+ IFile applicationMF2 = dir.getFile(AppConstants.APPLICATION_MF);
+
+ Assert.assertEqualsContract(file, applicationMF2, dir);
+ Assert.assertHashCodeEquals(file, applicationMF2, true);
+ }
+}
Added: aries/tags/application-0.2-incubating/application-utils/src/test/java/org/apache/aries/application/utils/filesystem/IOUtilsTest.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.2-incubating/application-utils/src/test/java/org/apache/aries/application/utils/filesystem/IOUtilsTest.java?rev=1075118&view=auto
==============================================================================
--- aries/tags/application-0.2-incubating/application-utils/src/test/java/org/apache/aries/application/utils/filesystem/IOUtilsTest.java (added)
+++ aries/tags/application-0.2-incubating/application-utils/src/test/java/org/apache/aries/application/utils/filesystem/IOUtilsTest.java Sun Feb 27 18:52:58 2011
@@ -0,0 +1,99 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.StringBufferInputStream;
+import java.util.zip.ZipFile;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class IOUtilsTest
+{
+ @BeforeClass
+ public static void setup()
+ {
+ new File("ioUtilsTest").mkdir();
+ }
+
+ @AfterClass
+ public static void cleanUp()
+ {
+ new File("ioUtilsTest/test.zip").delete();
+ IOUtils.deleteRecursive(new File("ioUtilsTest"));
+ }
+
+ @Test
+ public void testZipUp() throws IOException
+ {
+ IOUtils.zipUp(new File("../src/test/resources/zip"), new File("ioUtilsTest/test.zip"));
+
+ ZipFile zip = new ZipFile("ioUtilsTest/test.zip");
+ assertNotNull(zip.getEntry("file.txt"));
+ assertNotNull(zip.getEntry("subdir/someFile.txt"));
+ zip.close();
+ }
+
+ @Test
+ public void testWriteOut() throws IOException
+ {
+ File tmpDir = new File("ioUtilsTest/tmp");
+ tmpDir.mkdirs();
+
+ IOUtils.writeOut(tmpDir, "simple.txt", new StringBufferInputStream("abc"));
+ IOUtils.writeOut(tmpDir, "some/relative/directory/complex.txt", new StringBufferInputStream("def"));
+ IOUtils.writeOut(tmpDir, "some/relative/directory/complex2.txt", new StringBufferInputStream("ghi"));
+
+ File simple = new File("ioUtilsTest/tmp/simple.txt");
+ assertTrue(simple.exists());
+
+ File complex = new File("ioUtilsTest/tmp/some/relative/directory/complex.txt");
+ assertTrue(complex.exists());
+
+ File complex2 = new File("ioUtilsTest/tmp/some/relative/directory/complex2.txt");
+ assertTrue(complex2.exists());
+
+ BufferedReader r = new BufferedReader(new FileReader(simple));
+ assertEquals("abc", r.readLine());
+ assertNull(r.readLine());
+ r.close();
+
+ r = new BufferedReader(new FileReader(complex));
+ assertEquals("def", r.readLine());
+ assertNull(r.readLine());
+ r.close();
+
+ r = new BufferedReader(new FileReader(complex2));
+ assertEquals("ghi", r.readLine());
+ assertNull(r.readLine());
+ r.close();
+ }
+}
+
Added: aries/tags/application-0.2-incubating/application-utils/src/test/java/org/apache/aries/application/utils/manifest/BundleManifestTest.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.2-incubating/application-utils/src/test/java/org/apache/aries/application/utils/manifest/BundleManifestTest.java?rev=1075118&view=auto
==============================================================================
--- aries/tags/application-0.2-incubating/application-utils/src/test/java/org/apache/aries/application/utils/manifest/BundleManifestTest.java (added)
+++ aries/tags/application-0.2-incubating/application-utils/src/test/java/org/apache/aries/application/utils/manifest/BundleManifestTest.java Sun Feb 27 18:52:58 2011
@@ -0,0 +1,94 @@
+/*
+ * 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.manifest;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.util.jar.JarInputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import org.apache.aries.application.utils.filesystem.IOUtils;
+import org.apache.aries.application.utils.manifest.BundleManifest;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class BundleManifestTest
+{
+ private static File _testfile;
+
+ @BeforeClass
+ public static void setup() throws Exception
+ {
+ _testfile = new File ("./bundleManifestTest/nonExploded.jar");
+ _testfile.getParentFile().mkdirs();
+
+ ZipOutputStream out = new ZipOutputStream(new FileOutputStream(_testfile));
+ ZipEntry ze = new ZipEntry("META-INF/");
+ out.putNextEntry(ze);
+
+ File f = new File("../src/test/resources/bundles/exploded.jar/META-INF/beforeManifest.file");
+ ze = new ZipEntry("META-INF/beforeManifest.file");
+ ze.setSize(f.length());
+ out.putNextEntry(ze);
+ IOUtils.copy(new FileInputStream(f), out);
+
+ f = new File("../src/test/resources/bundles/exploded.jar/META-INF/MANIFEST.MF");
+ ze = new ZipEntry("META-INF/MANIFEST.MF");
+ ze.setSize(f.length());
+ out.putNextEntry(ze);
+ IOUtils.copy(new FileInputStream(f), out);
+
+ out.close();
+ }
+
+ @AfterClass
+ public static void cleanup()
+ {
+ _testfile.delete();
+ }
+
+ @Test
+ public void testExploded()
+ {
+ BundleManifest sut = BundleManifest.fromBundle(new File("../src/test/resources/bundles/exploded.jar"));
+ assertEquals("com.ibm.test", sut.getSymbolicName());
+ assertEquals("1.0.0", sut.getVersion().toString());
+ }
+
+ @Test
+ public void testZip() throws Exception
+ {
+ // make sure that the manifest is not the first file in the jar archive
+ JarInputStream jarIs = new JarInputStream(new FileInputStream(_testfile));
+ assertNull(jarIs.getManifest());
+ jarIs.close();
+
+ BundleManifest sut = BundleManifest.fromBundle(_testfile);
+ assertEquals("com.ibm.test", sut.getSymbolicName());
+ assertEquals("1.0.0", sut.getVersion().toString());
+ }
+}
+