Return-Path: Delivered-To: apmail-felix-commits-archive@www.apache.org Received: (qmail 55365 invoked from network); 7 May 2010 21:08:00 -0000 Received: from unknown (HELO mail.apache.org) (140.211.11.3) by 140.211.11.9 with SMTP; 7 May 2010 21:08:00 -0000 Received: (qmail 93693 invoked by uid 500); 7 May 2010 21:08:00 -0000 Delivered-To: apmail-felix-commits-archive@felix.apache.org Received: (qmail 93652 invoked by uid 500); 7 May 2010 21:08:00 -0000 Mailing-List: contact commits-help@felix.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@felix.apache.org Delivered-To: mailing list commits@felix.apache.org Received: (qmail 93645 invoked by uid 99); 7 May 2010 21:08:00 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 07 May 2010 21:08:00 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 07 May 2010 21:07:55 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id C98E523888DD; Fri, 7 May 2010 21:06:57 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r942225 - in /felix/trunk/gogo/felixcommands: ./ src/main/java/org/apache/felix/gogo/felixcommands/ Date: Fri, 07 May 2010 21:06:57 -0000 To: commits@felix.apache.org From: rickhall@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20100507210657.C98E523888DD@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: rickhall Date: Fri May 7 21:06:57 2010 New Revision: 942225 URL: http://svn.apache.org/viewvc?rev=942225&view=rev Log: Add support for OBR command. (FELIX-2042) Added: felix/trunk/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/OBR.java Modified: felix/trunk/gogo/felixcommands/pom.xml felix/trunk/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Activator.java felix/trunk/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Basic.java felix/trunk/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Inspect.java felix/trunk/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Util.java Modified: felix/trunk/gogo/felixcommands/pom.xml URL: http://svn.apache.org/viewvc/felix/trunk/gogo/felixcommands/pom.xml?rev=942225&r1=942224&r2=942225&view=diff ============================================================================== --- felix/trunk/gogo/felixcommands/pom.xml (original) +++ felix/trunk/gogo/felixcommands/pom.xml Fri May 7 21:06:57 2010 @@ -50,6 +50,11 @@ org.apache.felix.gogo.runtime 0.5.0-SNAPSHOT + + org.apache.felix + org.apache.felix.bundlerepository + 1.6.0 + @@ -74,6 +79,8 @@ ${artifactId} ${pom.artifactId} ${artifactId}.Activator + !org.apache.felix.bundlerepository.*, * + org.apache.felix.bundlerepository, org.apache.felix.bundlerepository.* Modified: felix/trunk/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Activator.java URL: http://svn.apache.org/viewvc/felix/trunk/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Activator.java?rev=942225&r1=942224&r2=942225&view=diff ============================================================================== --- felix/trunk/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Activator.java (original) +++ felix/trunk/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Activator.java Fri May 7 21:06:57 2010 @@ -21,9 +21,12 @@ package org.apache.felix.gogo.felixcomma 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 @@ public class Activator implements Bundle 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 Modified: felix/trunk/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Basic.java URL: http://svn.apache.org/viewvc/felix/trunk/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Basic.java?rev=942225&r1=942224&r2=942225&view=diff ============================================================================== --- felix/trunk/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Basic.java (original) +++ felix/trunk/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Basic.java Fri May 7 21:06:57 2010 @@ -30,6 +30,7 @@ import java.net.URL; 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 @@ public class Basic { 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 @@ public class Basic @Descriptor(description="target command") String name) { Map> commands = getCommands(); - List methods = commands.get(name); + + List 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> 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 @@ public class Basic 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 @@ public class Basic Method[] methods = svc.getClass().getMethods(); for (Method method : methods) { - List commandMethods = commands.get(method.getName()); + List commandMethods = commands.get(scope + ":" + method.getName()); if (commandMethods != null) { commandMethods.add(method); Modified: felix/trunk/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Inspect.java URL: http://svn.apache.org/viewvc/felix/trunk/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Inspect.java?rev=942225&r1=942224&r2=942225&view=diff ============================================================================== --- felix/trunk/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Inspect.java (original) +++ felix/trunk/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Inspect.java Fri May 7 21:06:57 2010 @@ -137,7 +137,7 @@ public class Inspect } 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 @@ public class Inspect 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 @@ public class Inspect } 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 @@ public class Inspect 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 @@ public class Inspect { 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 @@ public class Inspect { 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 @@ public class Inspect // 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 @@ public class Inspect // 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)) { Added: felix/trunk/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/OBR.java URL: http://svn.apache.org/viewvc/felix/trunk/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/OBR.java?rev=942225&view=auto ============================================================================== --- felix/trunk/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/OBR.java (added) +++ felix/trunk/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/OBR.java Fri May 7 21:06:57 2010 @@ -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="( | | )[@] ...") + 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="( | | )[@] ...") + 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="( | | )[@] ...") + 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="( | | )[@] ...") + 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 Modified: felix/trunk/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Util.java URL: http://svn.apache.org/viewvc/felix/trunk/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Util.java?rev=942225&r1=942224&r2=942225&view=diff ============================================================================== --- felix/trunk/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Util.java (original) +++ felix/trunk/gogo/felixcommands/src/main/java/org/apache/felix/gogo/felixcommands/Util.java Fri May 7 21:06:57 2010 @@ -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 @@ public class Util } 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 @@ public class Util 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