Add support for OBR command. (FELIX-2042)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@942225 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/gogo/felixcommands/pom.xml b/gogo/felixcommands/pom.xml
index e026e84..b617519 100644
--- a/gogo/felixcommands/pom.xml
+++ b/gogo/felixcommands/pom.xml
@@ -50,6 +50,11 @@
<artifactId>org.apache.felix.gogo.runtime</artifactId>
<version>0.5.0-SNAPSHOT</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.bundlerepository</artifactId>
+ <version>1.6.0</version>
+ </dependency>
</dependencies>
<build>
@@ -74,6 +79,8 @@
<Bundle-SymbolicName>${artifactId}</Bundle-SymbolicName>
<Private-Package>${pom.artifactId}</Private-Package>
<Bundle-Activator>${artifactId}.Activator</Bundle-Activator>
+ <Import-Package>!org.apache.felix.bundlerepository.*, *</Import-Package>
+ <DynamicImport-Package>org.apache.felix.bundlerepository, org.apache.felix.bundlerepository.*</DynamicImport-Package>
</instructions>
</configuration>
</plugin>
diff --git a/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Activator.java b/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Activator.java
index 9ecd1e6..626a71f 100644
--- a/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Activator.java
+++ b/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Activator.java
@@ -21,9 +21,12 @@
import java.util.Hashtable;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
+import org.osgi.util.tracker.ServiceTracker;
public class Activator implements BundleActivator
{
+ private volatile ServiceTracker m_tracker = null;
+
public void start(BundleContext bc) throws Exception
{
Hashtable props = new Hashtable();
@@ -40,9 +43,19 @@
props.put("osgi.command.function", new String[] { "ls" });
bc.registerService(
Files.class.getName(), new Files(bc), props);
+
+ m_tracker = new ServiceTracker(
+ bc, "org.apache.felix.bundlerepository.RepositoryAdmin", null);
+ m_tracker.open();
+ props.put("osgi.command.scope", "obr");
+ props.put("osgi.command.function", new String[] {
+ "deploy", "info", "javadoc", "list", "repos", "source" });
+ bc.registerService(
+ OBR.class.getName(), new OBR(bc, m_tracker), props);
}
public void stop(BundleContext bc) throws Exception
{
+ m_tracker.close();
}
}
\ No newline at end of file
diff --git a/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Basic.java b/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Basic.java
index b7d56e8..13d70ad 100644
--- a/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Basic.java
+++ b/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Basic.java
@@ -30,6 +30,7 @@
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Comparator;
import java.util.Date;
import java.util.Dictionary;
import java.util.Enumeration;
@@ -191,7 +192,7 @@
{
String title = Util.getBundleName(bundle);
System.out.println("\n" + title);
- System.out.println(Util.getUnderlineString(title));
+ System.out.println(Util.getUnderlineString(title.length()));
Dictionary dict = bundle.getHeaders();
Enumeration keys = dict.keys();
while (keys.hasMoreElements())
@@ -218,7 +219,30 @@
@Descriptor(description="target command") String name)
{
Map<String, List<Method>> commands = getCommands();
- List<Method> methods = commands.get(name);
+
+ List<Method> methods = null;
+
+ // If the specified command doesn't have a scope, then
+ // search for matching methods by ignoring the scope.
+ int scopeIdx = name.indexOf(':');
+ if (scopeIdx < 0)
+ {
+ for (Entry<String, List<Method>> entry : commands.entrySet())
+ {
+ String k = entry.getKey().substring(entry.getKey().indexOf(':') + 1);
+ if (name.equals(k))
+ {
+ methods = entry.getValue();
+ break;
+ }
+ }
+ }
+ // Otherwise directly look up matching methods.
+ else
+ {
+ methods = commands.get(name);
+ }
+
if ((methods != null) && (methods.size() > 0))
{
for (Method m : methods)
@@ -324,11 +348,12 @@
Object svc = m_bc.getService(ref);
if (svc != null)
{
+ String scope = (String) ref.getProperty("osgi.command.scope");
String[] funcs = (String[]) ref.getProperty("osgi.command.function");
for (String func : funcs)
{
- commands.put(func, new ArrayList());
+ commands.put(scope + ":" + func, new ArrayList());
}
if (!commands.isEmpty())
@@ -336,7 +361,7 @@
Method[] methods = svc.getClass().getMethods();
for (Method method : methods)
{
- List<Method> commandMethods = commands.get(method.getName());
+ List<Method> commandMethods = commands.get(scope + ":" + method.getName());
if (commandMethods != null)
{
commandMethods.add(method);
diff --git a/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Inspect.java b/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Inspect.java
index d17c344..401ac1a 100644
--- a/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Inspect.java
+++ b/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Inspect.java
@@ -137,7 +137,7 @@
}
String title = bundles[bundleIdx] + " exports packages:";
System.out.println(title);
- System.out.println(Util.getUnderlineString(title));
+ System.out.println(Util.getUnderlineString(title.length()));
if ((exports != null) && (exports.length > 0))
{
for (int expIdx = 0; expIdx < exports.length; expIdx++)
@@ -220,7 +220,7 @@
ExportedPackage[] exports = pa.getExportedPackages((Bundle) null);
String title = bundle + " imports packages:";
System.out.println(title);
- System.out.println(Util.getUnderlineString(title));
+ System.out.println(Util.getUnderlineString(title.length()));
boolean found = false;
for (int expIdx = 0; expIdx < exports.length; expIdx++)
{
@@ -281,7 +281,7 @@
}
String title = bundles[bundleIdx] + " is required by:";
System.out.println(title);
- System.out.println(Util.getUnderlineString(title));
+ System.out.println(Util.getUnderlineString(title.length()));
if ((rbs[rbIdx].getRequiringBundles() != null)
&& (rbs[rbIdx].getRequiringBundles().length > 0))
{
@@ -356,7 +356,7 @@
RequiredBundle[] rbs = pa.getRequiredBundles(null);
String title = bundle + " requires bundles:";
System.out.println(title);
- System.out.println(Util.getUnderlineString(title));
+ System.out.println(Util.getUnderlineString(title.length()));
boolean found = false;
for (int rbIdx = 0; rbIdx < rbs.length; rbIdx++)
{
@@ -410,7 +410,7 @@
{
String title = bundles[bundleIdx] + " is attached to:";
System.out.println(title);
- System.out.println(Util.getUnderlineString(title));
+ System.out.println(Util.getUnderlineString(title.length()));
Bundle[] hosts = pa.getHosts(bundles[bundleIdx]);
for (int hostIdx = 0;
(hosts != null) && (hostIdx < hosts.length);
@@ -469,7 +469,7 @@
{
String title = bundles[bundleIdx] + " hosts:";
System.out.println(title);
- System.out.println(Util.getUnderlineString(title));
+ System.out.println(Util.getUnderlineString(title.length()));
Bundle[] fragments = pa.getFragments(bundles[bundleIdx]);
for (int fragIdx = 0;
(fragments != null) && (fragIdx < fragments.length);
@@ -520,7 +520,7 @@
// Print header if we have not already done so.
String title = Util.getBundleName(bundles[bundleIdx]) + " provides services:";
System.out.println(title);
- System.out.println(Util.getUnderlineString(title));
+ System.out.println(Util.getUnderlineString(title.length()));
if ((refs == null) || (refs.length == 0))
{
@@ -582,7 +582,7 @@
// Print header if we have not already done so.
String title = Util.getBundleName(bundles[bundleIdx]) + " requires services:";
System.out.println(title);
- System.out.println(Util.getUnderlineString(title));
+ System.out.println(Util.getUnderlineString(title.length()));
if ((refs == null) || (refs.length == 0))
{
diff --git a/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/OBR.java b/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/OBR.java
new file mode 100644
index 0000000..e2205ab
--- /dev/null
+++ b/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/OBR.java
@@ -0,0 +1,637 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.gogo.felixcommands;
+
+import java.io.*;
+import java.lang.reflect.Array;
+import java.net.URL;
+import java.util.*;
+import org.apache.felix.bundlerepository.Capability;
+import org.apache.felix.bundlerepository.Reason;
+
+import org.apache.felix.bundlerepository.RepositoryAdmin;
+import org.apache.felix.bundlerepository.Requirement;
+import org.apache.felix.bundlerepository.Resolver;
+import org.apache.felix.bundlerepository.Resource;
+import org.osgi.framework.*;
+import org.osgi.service.command.Descriptor;
+import org.osgi.service.command.Flag;
+import org.osgi.util.tracker.ServiceTracker;
+
+public class OBR
+{
+ private static final String REPO_ADD = "add";
+ private static final String REPO_REMOVE = "remove";
+ private static final String REPO_LIST = "list";
+ private static final String REPO_REFRESH = "refresh";
+
+ private static final char VERSION_SEPARATOR = '@';
+
+ private final BundleContext m_bc;
+ private final ServiceTracker m_tracker;
+
+ public OBR(BundleContext bc, ServiceTracker tracker)
+ {
+ m_bc = bc;
+ m_tracker = tracker;
+ }
+
+ private RepositoryAdmin getRepositoryAdmin()
+ {
+ Object svcObj;
+ try
+ {
+ svcObj = m_tracker.getService();
+ }
+ catch (Exception ex)
+ {
+ svcObj = null;
+ }
+ if (svcObj == null)
+ {
+ System.out.println("No repository admin service available");
+ }
+ return (RepositoryAdmin) svcObj;
+ }
+
+ @Descriptor(description="manage repositories")
+ public void repos(
+ @Descriptor(description="( add | list | refresh | remove )") String action,
+ @Descriptor(description="space-delimited list of repository URLs") String[] args)
+ throws IOException
+ {
+ Object svcObj = getRepositoryAdmin();
+ if (svcObj == null)
+ {
+ return;
+ }
+ RepositoryAdmin ra = (RepositoryAdmin) svcObj;
+
+ if (args.length > 0)
+ {
+ for (int i = 0; i < args.length; i++)
+ {
+ try
+ {
+ if (action.equals(REPO_ADD))
+ {
+ ra.addRepository(args[i]);
+ }
+ else if (action.equals(REPO_REFRESH))
+ {
+ ra.removeRepository(args[i]);
+ ra.addRepository(args[i]);
+ }
+ else if (action.equals(REPO_REMOVE))
+ {
+ ra.removeRepository(args[i]);
+ }
+ else
+ {
+ System.out.println("Unknown repository operation: " + action);
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace(System.err);
+ }
+ }
+ }
+ else
+ {
+ org.apache.felix.bundlerepository.Repository[] repos =
+ ra.listRepositories();
+ if ((repos != null) && (repos.length > 0))
+ {
+ for (int i = 0; i < repos.length; i++)
+ {
+ System.out.println(repos[i].getURI());
+ }
+ }
+ else
+ {
+ System.out.println("No repository URLs are set.");
+ }
+ }
+ }
+
+ @Descriptor(description="list repository resources")
+ public void list(
+ @Flag(name="-v", description="verbose") boolean verbose,
+ @Descriptor(description="optional strings used for name matching") String[] args)
+ throws IOException, InvalidSyntaxException
+ {
+ Object svcObj = getRepositoryAdmin();
+ if (svcObj == null)
+ {
+ return;
+ }
+ RepositoryAdmin ra = (RepositoryAdmin) svcObj;
+
+ // Create a filter that will match presentation name or symbolic name.
+ StringBuffer sb = new StringBuffer();
+ if ((args == null) || (args.length == 0))
+ {
+ sb.append("(|(presentationname=*)(symbolicname=*))");
+ }
+ else
+ {
+ StringBuffer value = new StringBuffer();
+ for (int i = 0; i < args.length; i++)
+ {
+ if (i > 0)
+ {
+ value.append(" ");
+ }
+ value.append(args[i]);
+ }
+ sb.append("(|(presentationname=*");
+ sb.append(value);
+ sb.append("*)(symbolicname=*");
+ sb.append(value);
+ sb.append("*))");
+ }
+ // Use filter to get matching resources.
+ Resource[] resources = ra.discoverResources(sb.toString());
+
+ // Group the resources by symbolic name in descending version order,
+ // but keep them in overall sorted order by presentation name.
+ Map revisionMap = new TreeMap(new Comparator() {
+ public int compare(Object o1, Object o2)
+ {
+ Resource r1 = (Resource) o1;
+ Resource r2 = (Resource) o2;
+ // Assume if the symbolic name is equal, then the two are equal,
+ // since we are trying to aggregate by symbolic name.
+ int symCompare = r1.getSymbolicName().compareTo(r2.getSymbolicName());
+ if (symCompare == 0)
+ {
+ return 0;
+ }
+ // Otherwise, compare the presentation name to keep them sorted
+ // by presentation name. If the presentation names are equal, then
+ // use the symbolic name to differentiate.
+ int compare = (r1.getPresentationName() == null)
+ ? -1
+ : (r2.getPresentationName() == null)
+ ? 1
+ : r1.getPresentationName().compareToIgnoreCase(
+ r2.getPresentationName());
+ if (compare == 0)
+ {
+ return symCompare;
+ }
+ return compare;
+ }
+ });
+ for (int resIdx = 0; (resources != null) && (resIdx < resources.length); resIdx++)
+ {
+ Resource[] revisions = (Resource[]) revisionMap.get(resources[resIdx]);
+ revisionMap.put(resources[resIdx], addResourceByVersion(revisions, resources[resIdx]));
+ }
+
+ // Print any matching resources.
+ for (Iterator i = revisionMap.entrySet().iterator(); i.hasNext(); )
+ {
+ Map.Entry entry = (Map.Entry) i.next();
+ Resource[] revisions = (Resource[]) entry.getValue();
+ String name = revisions[0].getPresentationName();
+ name = (name == null) ? revisions[0].getSymbolicName() : name;
+ System.out.print(name);
+
+ if (verbose && revisions[0].getPresentationName() != null)
+ {
+ System.out.print(" [" + revisions[0].getSymbolicName() + "]");
+ }
+
+ System.out.print(" (");
+ int revIdx = 0;
+ do
+ {
+ if (revIdx > 0)
+ {
+ System.out.print(", ");
+ }
+ System.out.print(revisions[revIdx].getVersion());
+ revIdx++;
+ }
+ while (verbose && (revIdx < revisions.length));
+ if (!verbose && (revisions.length > 1))
+ {
+ System.out.print(", ...");
+ }
+ System.out.println(")");
+ }
+
+ if ((resources == null) || (resources.length == 0))
+ {
+ System.out.println("No matching bundles.");
+ }
+ }
+
+ @Descriptor(description="retrieve resource description from repository")
+ public void info(
+ @Descriptor(description="( <bundle-name> | <symbolic-name> | <bundle-id> )[@<version>] ...")
+ String[] args)
+ throws IOException, InvalidSyntaxException
+ {
+ Object svcObj = getRepositoryAdmin();
+ if (svcObj == null)
+ {
+ return;
+ }
+ RepositoryAdmin ra = (RepositoryAdmin) svcObj;
+
+ for (int argIdx = 0; (args != null) && (argIdx < args.length); argIdx++)
+ {
+ // Find the target's bundle resource.
+ String targetName = args[argIdx];
+ String targetVersion = null;
+ int idx = args[argIdx].indexOf(VERSION_SEPARATOR);
+ if (idx > 0)
+ {
+ targetName = args[argIdx].substring(0, idx);
+ targetVersion = args[argIdx].substring(idx + 1);
+ }
+ Resource[] resources = searchRepository(ra, targetName, targetVersion);
+ if (resources == null)
+ {
+ System.err.println("Unknown bundle and/or version: " + args[argIdx]);
+ }
+ else
+ {
+ for (int resIdx = 0; resIdx < resources.length; resIdx++)
+ {
+ if (resIdx > 0)
+ {
+ System.out.println("");
+ }
+ printResource(System.out, resources[resIdx]);
+ }
+ }
+ }
+ }
+
+ @Descriptor(description="deploy resource from repository")
+ public void deploy(
+ @Flag(name="-s", description="start deployed bundles") boolean start,
+ @Descriptor(description="( <bundle-name> | <symbolic-name> | <bundle-id> )[@<version>] ...")
+ String[] args)
+ throws IOException, InvalidSyntaxException
+ {
+ Object svcObj = getRepositoryAdmin();
+ if (svcObj == null)
+ {
+ return;
+ }
+ RepositoryAdmin ra = (RepositoryAdmin) svcObj;
+
+ Resolver resolver = ra.resolver();
+ for (int argIdx = 0; (args != null) && (argIdx < args.length); argIdx++)
+ {
+ // Find the target's bundle resource.
+ String targetName = args[argIdx];
+ String targetVersion = null;
+ int idx = args[argIdx].indexOf(VERSION_SEPARATOR);
+ if (idx > 0)
+ {
+ targetName = args[argIdx].substring(0, idx);
+ targetVersion = args[argIdx].substring(idx + 1);
+ }
+ Resource resource = selectNewestVersion(
+ searchRepository(ra, targetName, targetVersion));
+ if (resource != null)
+ {
+ resolver.add(resource);
+ }
+ else
+ {
+ System.err.println("Unknown bundle - " + args[argIdx]);
+ }
+ }
+
+ if ((resolver.getAddedResources() != null) &&
+ (resolver.getAddedResources().length > 0))
+ {
+ if (resolver.resolve())
+ {
+ System.out.println("Target resource(s):");
+ System.out.println(Util.getUnderlineString(19));
+ Resource[] resources = resolver.getAddedResources();
+ for (int resIdx = 0; (resources != null) && (resIdx < resources.length); resIdx++)
+ {
+ System.out.println(" " + resources[resIdx].getPresentationName()
+ + " (" + resources[resIdx].getVersion() + ")");
+ }
+ resources = resolver.getRequiredResources();
+ if ((resources != null) && (resources.length > 0))
+ {
+ System.out.println("\nRequired resource(s):");
+ System.out.println(Util.getUnderlineString(21));
+ for (int resIdx = 0; resIdx < resources.length; resIdx++)
+ {
+ System.out.println(" " + resources[resIdx].getPresentationName()
+ + " (" + resources[resIdx].getVersion() + ")");
+ }
+ }
+ resources = resolver.getOptionalResources();
+ if ((resources != null) && (resources.length > 0))
+ {
+ System.out.println("\nOptional resource(s):");
+ System.out.println(Util.getUnderlineString(21));
+ for (int resIdx = 0; resIdx < resources.length; resIdx++)
+ {
+ System.out.println(" " + resources[resIdx].getPresentationName()
+ + " (" + resources[resIdx].getVersion() + ")");
+ }
+ }
+
+ try
+ {
+ System.out.print("\nDeploying...");
+ resolver.deploy(start ? Resolver.START : 0);
+ System.out.println("done.");
+ }
+ catch (IllegalStateException ex)
+ {
+ System.err.println(ex);
+ }
+ }
+ else
+ {
+ Reason[] reqs = resolver.getUnsatisfiedRequirements();
+ if ((reqs != null) && (reqs.length > 0))
+ {
+ System.out.println("Unsatisfied requirement(s):");
+ System.out.println(Util.getUnderlineString(27));
+ for (int reqIdx = 0; reqIdx < reqs.length; reqIdx++)
+ {
+ System.out.println(" " + reqs[reqIdx].getRequirement().getFilter());
+ System.out.println(" " + reqs[reqIdx].getResource().getPresentationName());
+ }
+ }
+ else
+ {
+ System.out.println("Could not resolve targets.");
+ }
+ }
+ }
+ }
+
+ @Descriptor(description="retrieve resource source code from repository")
+ public void source(
+ @Flag(name="-x", description="extract") boolean extract,
+ @Descriptor(description="local target directory") File localDir,
+ @Descriptor(description="( <bundle-name> | <symbolic-name> | <bundle-id> )[@<version>] ...")
+ String[] args)
+ throws IOException, InvalidSyntaxException
+ {
+ Object svcObj = getRepositoryAdmin();
+ if (svcObj == null)
+ {
+ return;
+ }
+ RepositoryAdmin ra = (RepositoryAdmin) svcObj;
+
+ for (int argIdx = 0; argIdx < args.length; argIdx++)
+ {
+ // Find the target's bundle resource.
+ String targetName = args[argIdx];
+ String targetVersion = null;
+ int idx = args[argIdx].indexOf(VERSION_SEPARATOR);
+ if (idx > 0)
+ {
+ targetName = args[argIdx].substring(0, idx);
+ targetVersion = args[argIdx].substring(idx + 1);
+ }
+ Resource resource = selectNewestVersion(
+ searchRepository(ra, targetName, targetVersion));
+ if (resource == null)
+ {
+ System.err.println("Unknown bundle and/or version: " + args[argIdx]);
+ }
+ else
+ {
+ String srcURI = (String) resource.getProperties().get(Resource.SOURCE_URI);
+ if (srcURI != null)
+ {
+ Util.downloadSource(
+ System.out, System.err, new URL(srcURI),
+ localDir, extract);
+ }
+ else
+ {
+ System.err.println("Missing source URL: " + args[argIdx]);
+ }
+ }
+ }
+ }
+
+ @Descriptor(description="retrieve resource JavaDoc from repository")
+ public void javadoc(
+ @Flag(name="-x", description="extract") boolean extract,
+ @Descriptor(description="local target directory") File localDir,
+ @Descriptor(description="( <bundle-name> | <symbolic-name> | <bundle-id> )[@<version>] ...")
+ String[] args)
+ throws IOException, InvalidSyntaxException
+ {
+ Object svcObj = getRepositoryAdmin();
+ if (svcObj == null)
+ {
+ return;
+ }
+ RepositoryAdmin ra = (RepositoryAdmin) svcObj;
+
+ for (int argIdx = 0; argIdx < args.length; argIdx++)
+ {
+ // Find the target's bundle resource.
+ String targetName = args[argIdx];
+ String targetVersion = null;
+ int idx = args[argIdx].indexOf(VERSION_SEPARATOR);
+ if (idx > 0)
+ {
+ targetName = args[argIdx].substring(0, idx);
+ targetVersion = args[argIdx].substring(idx + 1);
+ }
+ Resource resource = selectNewestVersion(
+ searchRepository(ra, targetName, targetVersion));
+ if (resource == null)
+ {
+ System.err.println("Unknown bundle and/or version: " + args[argIdx]);
+ }
+ else
+ {
+ URL docURL = (URL) resource.getProperties().get("javadoc");
+ if (docURL != null)
+ {
+ Util.downloadSource(
+ System.out, System.err, docURL, localDir, extract);
+ }
+ else
+ {
+ System.err.println("Missing javadoc URL: " + args[argIdx]);
+ }
+ }
+ }
+ }
+
+ private Resource[] searchRepository(
+ RepositoryAdmin ra, String targetId, String targetVersion)
+ throws InvalidSyntaxException
+ {
+ // Try to see if the targetId is a bundle ID.
+ try
+ {
+ Bundle bundle = m_bc.getBundle(Long.parseLong(targetId));
+ targetId = bundle.getSymbolicName();
+ }
+ catch (NumberFormatException ex)
+ {
+ // It was not a number, so ignore.
+ }
+
+ // The targetId may be a bundle name or a bundle symbolic name,
+ // so create the appropriate LDAP query.
+ StringBuffer sb = new StringBuffer("(|(presentationname=");
+ sb.append(targetId);
+ sb.append(")(symbolicname=");
+ sb.append(targetId);
+ sb.append("))");
+ if (targetVersion != null)
+ {
+ sb.insert(0, "(&");
+ sb.append("(version=");
+ sb.append(targetVersion);
+ sb.append("))");
+ }
+ return ra.discoverResources(sb.toString());
+ }
+
+ private Resource selectNewestVersion(Resource[] resources)
+ {
+ int idx = -1;
+ Version v = null;
+ for (int i = 0; (resources != null) && (i < resources.length); i++)
+ {
+ if (i == 0)
+ {
+ idx = 0;
+ v = resources[i].getVersion();
+ }
+ else
+ {
+ Version vtmp = resources[i].getVersion();
+ if (vtmp.compareTo(v) > 0)
+ {
+ idx = i;
+ v = vtmp;
+ }
+ }
+ }
+
+ return (idx < 0) ? null : resources[idx];
+ }
+
+ private void printResource(PrintStream out, Resource resource)
+ {
+ System.out.println(Util.getUnderlineString(resource.getPresentationName().length()));
+ out.println(resource.getPresentationName());
+ System.out.println(Util.getUnderlineString(resource.getPresentationName().length()));
+
+ Map map = resource.getProperties();
+ for (Iterator iter = map.entrySet().iterator(); iter.hasNext(); )
+ {
+ Map.Entry entry = (Map.Entry) iter.next();
+ if (entry.getValue().getClass().isArray())
+ {
+ out.println(entry.getKey() + ":");
+ for (int j = 0; j < Array.getLength(entry.getValue()); j++)
+ {
+ out.println(" " + Array.get(entry.getValue(), j));
+ }
+ }
+ else
+ {
+ out.println(entry.getKey() + ": " + entry.getValue());
+ }
+ }
+
+ Requirement[] reqs = resource.getRequirements();
+ if ((reqs != null) && (reqs.length > 0))
+ {
+ out.println("Requires:");
+ for (int i = 0; i < reqs.length; i++)
+ {
+ out.println(" " + reqs[i].getFilter());
+ }
+ }
+
+ Capability[] caps = resource.getCapabilities();
+ if ((caps != null) && (caps.length > 0))
+ {
+ out.println("Capabilities:");
+ for (int i = 0; i < caps.length; i++)
+ {
+ out.println(" " + caps[i].getPropertiesAsMap());
+ }
+ }
+ }
+
+ private static Resource[] addResourceByVersion(Resource[] revisions, Resource resource)
+ {
+ // We want to add the resource into the array of revisions
+ // in descending version sorted order (i.e., newest first)
+ Resource[] sorted = null;
+ if (revisions == null)
+ {
+ sorted = new Resource[] { resource };
+ }
+ else
+ {
+ Version version = resource.getVersion();
+ Version middleVersion = null;
+ int top = 0, bottom = revisions.length - 1, middle = 0;
+ while (top <= bottom)
+ {
+ middle = (bottom - top) / 2 + top;
+ middleVersion = revisions[middle].getVersion();
+ // Sort in reverse version order.
+ int cmp = middleVersion.compareTo(version);
+ if (cmp < 0)
+ {
+ bottom = middle - 1;
+ }
+ else
+ {
+ top = middle + 1;
+ }
+ }
+
+ // Ignore duplicates.
+ if ((top >= revisions.length) || (revisions[top] != resource))
+ {
+ sorted = new Resource[revisions.length + 1];
+ System.arraycopy(revisions, 0, sorted, 0, top);
+ System.arraycopy(revisions, top, sorted, top + 1, revisions.length - top);
+ sorted[top] = resource;
+ }
+ }
+ return sorted;
+ }
+}
\ No newline at end of file
diff --git a/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Util.java b/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Util.java
index 03021dc..d3602bc 100644
--- a/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Util.java
+++ b/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Util.java
@@ -18,7 +18,21 @@
*/
package org.apache.felix.gogo.felixcommands;
+import java.io.BufferedOutputStream;
+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.io.PrintStream;
+import java.net.URL;
+import java.net.URLConnection;
import java.util.List;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+import org.apache.felix.bundlerepository.impl.Base64Encoder;
+import org.apache.felix.bundlerepository.impl.FileUtil;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
@@ -39,12 +53,12 @@
}
private final static StringBuffer m_sb = new StringBuffer();
- public static String getUnderlineString(String s)
+ public static String getUnderlineString(int len)
{
synchronized (m_sb)
{
m_sb.delete(0, m_sb.length());
- for (int i = 0; i < s.length(); i++)
+ for (int i = 0; i < len; i++)
{
m_sb.append('-');
}
@@ -132,4 +146,176 @@
bc.ungetService(refs.remove(0));
}
}
+
+ public static void downloadSource(
+ PrintStream out, PrintStream err,
+ URL srcURL, File localDir, boolean extract)
+ {
+ // Get the file name from the URL.
+ String fileName = (srcURL.getFile().lastIndexOf('/') > 0)
+ ? srcURL.getFile().substring(srcURL.getFile().lastIndexOf('/') + 1)
+ : srcURL.getFile();
+
+ try
+ {
+ out.println("Connecting...");
+
+ if (!localDir.exists())
+ {
+ err.println("Destination directory does not exist.");
+ }
+ File file = new File(localDir, fileName);
+
+ OutputStream os = new FileOutputStream(file);
+ URLConnection conn = srcURL.openConnection();
+ Util.setProxyAuth(conn);
+ int total = conn.getContentLength();
+ InputStream is = conn.getInputStream();
+
+ if (total > 0)
+ {
+ out.println("Downloading " + fileName
+ + " ( " + total + " bytes ).");
+ }
+ else
+ {
+ out.println("Downloading " + fileName + ".");
+ }
+ byte[] buffer = new byte[4096];
+ int count = 0;
+ for (int len = is.read(buffer); len > 0; len = is.read(buffer))
+ {
+ count += len;
+ os.write(buffer, 0, len);
+ }
+
+ os.close();
+ is.close();
+
+ if (extract)
+ {
+ is = new FileInputStream(file);
+ JarInputStream jis = new JarInputStream(is);
+ out.println("Extracting...");
+ unjar(jis, localDir);
+ jis.close();
+ file.delete();
+ }
+ }
+ catch (Exception ex)
+ {
+ err.println(ex);
+ }
+ }
+
+ public static void unjar(JarInputStream jis, File dir)
+ throws IOException
+ {
+ // Reusable buffer.
+ byte[] buffer = new byte[4096];
+
+ // Loop through JAR entries.
+ for (JarEntry je = jis.getNextJarEntry();
+ je != null;
+ je = jis.getNextJarEntry())
+ {
+ if (je.getName().startsWith("/"))
+ {
+ throw new IOException("JAR resource cannot contain absolute paths.");
+ }
+
+ File target = new File(dir, je.getName());
+
+ // Check to see if the JAR entry is a directory.
+ if (je.isDirectory())
+ {
+ if (!target.exists())
+ {
+ if (!target.mkdirs())
+ {
+ throw new IOException("Unable to create target directory: "
+ + target);
+ }
+ }
+ // Just continue since directories do not have content to copy.
+ continue;
+ }
+
+ int lastIndex = je.getName().lastIndexOf('/');
+ String name = (lastIndex >= 0) ?
+ je.getName().substring(lastIndex + 1) : je.getName();
+ String destination = (lastIndex >= 0) ?
+ je.getName().substring(0, lastIndex) : "";
+
+ // JAR files use '/', so convert it to platform separator.
+ destination = destination.replace('/', File.separatorChar);
+ copy(jis, dir, name, destination, buffer);
+ }
+ }
+
+ public static void copy(
+ InputStream is, File dir, String destName, String destDir, byte[] buffer)
+ throws IOException
+ {
+ if (destDir == null)
+ {
+ destDir = "";
+ }
+
+ // Make sure the target directory exists and
+ // that is actually a directory.
+ File targetDir = new File(dir, destDir);
+ if (!targetDir.exists())
+ {
+ if (!targetDir.mkdirs())
+ {
+ throw new IOException("Unable to create target directory: "
+ + targetDir);
+ }
+ }
+ else if (!targetDir.isDirectory())
+ {
+ throw new IOException("Target is not a directory: "
+ + targetDir);
+ }
+
+ BufferedOutputStream bos = new BufferedOutputStream(
+ new FileOutputStream(new File(targetDir, destName)));
+ int count = 0;
+ while ((count = is.read(buffer)) > 0)
+ {
+ bos.write(buffer, 0, count);
+ }
+ bos.close();
+ }
+
+ public static void setProxyAuth(URLConnection conn) throws IOException
+ {
+ // Support for http proxy authentication
+ String auth = System.getProperty("http.proxyAuth");
+ if ((auth != null) && (auth.length() > 0))
+ {
+ if ("http".equals(conn.getURL().getProtocol())
+ || "https".equals(conn.getURL().getProtocol()))
+ {
+ String base64 = Base64Encoder.base64Encode(auth);
+ conn.setRequestProperty("Proxy-Authorization", "Basic " + base64);
+ }
+ }
+ }
+
+ public static InputStream openURL(final URL url) throws IOException
+ {
+ // Do it the manual way to have a chance to
+ // set request properties as proxy auth (EW).
+ return openURL(url.openConnection());
+ }
+
+ public static InputStream openURL(final URLConnection conn) throws IOException
+ {
+ // Do it the manual way to have a chance to
+ // set request properties as proxy auth (EW).
+ setProxyAuth(conn);
+ return conn.getInputStream();
+ }
}
\ No newline at end of file