blob: e784c97c91131d65251b57dd4b3f1e4007e9a3c1 [file] [log] [blame]
/*
* 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.bundlerepository.impl;
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.Requirement;
import org.apache.felix.bundlerepository.Resolver;
import org.apache.felix.bundlerepository.Resource;
import org.apache.felix.bundlerepository.impl.FileUtil;
import org.apache.felix.shell.Command;
import org.osgi.framework.*;
public class ObrCommandImpl implements Command
{
private static final String HELP_CMD = "help";
private static final String ADDURL_CMD = "add-url";
private static final String REMOVEURL_CMD = "remove-url";
private static final String LISTURL_CMD = "list-url";
private static final String REFRESHURL_CMD = "refresh-url";
private static final String LIST_CMD = "list";
private static final String INFO_CMD = "info";
private static final String DEPLOY_CMD = "deploy";
private static final String START_CMD = "start";
private static final String SOURCE_CMD = "source";
private static final String JAVADOC_CMD = "javadoc";
private static final String EXTRACT_SWITCH = "-x";
private static final String VERBOSE_SWITCH = "-v";
private BundleContext m_context = null;
private org.apache.felix.bundlerepository.RepositoryAdmin m_repoAdmin = null;
public ObrCommandImpl(BundleContext context, org.apache.felix.bundlerepository.RepositoryAdmin repoAdmin)
{
m_context = context;
m_repoAdmin = repoAdmin;
}
public String getName()
{
return "obr";
}
public String getUsage()
{
return "obr help";
}
public String getShortDescription()
{
return "OSGi bundle repository.";
}
public synchronized void execute(String commandLine, PrintStream out, PrintStream err)
{
try
{
// Parse the commandLine to get the OBR command.
StringTokenizer st = new StringTokenizer(commandLine);
// Ignore the invoking command.
st.nextToken();
// Try to get the OBR command, default is HELP command.
String command = HELP_CMD;
try
{
command = st.nextToken();
}
catch (Exception ex)
{
// Ignore.
}
// Perform the specified command.
if ((command == null) || (command.equals(HELP_CMD)))
{
help(out, st);
}
else
{
if (command.equals(ADDURL_CMD) ||
command.equals(REFRESHURL_CMD) ||
command.equals(REMOVEURL_CMD) ||
command.equals(LISTURL_CMD))
{
urls(commandLine, command, out, err);
}
else if (command.equals(LIST_CMD))
{
list(commandLine, command, out, err);
}
else if (command.equals(INFO_CMD))
{
info(commandLine, command, out, err);
}
else if (command.equals(DEPLOY_CMD) || command.equals(START_CMD))
{
deploy(commandLine, command, out, err);
}
else if (command.equals(SOURCE_CMD))
{
source(commandLine, command, out, err);
}
else if (command.equals(JAVADOC_CMD))
{
javadoc(commandLine, command, out, err);
}
else
{
err.println("Unknown command: " + command);
}
}
}
catch (InvalidSyntaxException ex)
{
err.println("Syntax error: " + ex.getMessage());
}
catch (IOException ex)
{
err.println("Error: " + ex);
}
}
private void urls(
String commandLine, String command, PrintStream out, PrintStream err)
throws IOException
{
// Parse the commandLine.
StringTokenizer st = new StringTokenizer(commandLine);
// Ignore the "obr" command.
st.nextToken();
// Ignore the "url" command.
st.nextToken();
int count = st.countTokens();
if (count > 0)
{
while (st.hasMoreTokens())
{
try
{
String uri = st.nextToken();
if (command.equals(ADDURL_CMD))
{
m_repoAdmin.addRepository(uri);
}
else if (command.equals(REFRESHURL_CMD))
{
m_repoAdmin.removeRepository(uri);
m_repoAdmin.addRepository(uri);
}
else
{
m_repoAdmin.removeRepository(uri);
}
}
catch (Exception ex)
{
ex.printStackTrace(err);
}
}
}
else
{
org.apache.felix.bundlerepository.Repository[] repos = m_repoAdmin.listRepositories();
if ((repos != null) && (repos.length > 0))
{
for (int i = 0; i < repos.length; i++)
{
out.println(repos[i].getURI());
}
}
else
{
out.println("No repository URLs are set.");
}
}
}
private void list(
String commandLine, String command, PrintStream out, PrintStream err)
throws IOException, InvalidSyntaxException
{
// Parse the command for an option switch and tokens.
ParsedCommand pc = parseList(commandLine);
// Create a filter that will match presentation name or symbolic name.
StringBuffer sb = new StringBuffer();
if ((pc.getTokens() == null) || (pc.getTokens().length() == 0))
{
sb.append("(|(presentationname=*)(symbolicname=*))");
}
else
{
sb.append("(|(presentationname=*");
sb.append(pc.getTokens());
sb.append("*)(symbolicname=*");
sb.append(pc.getTokens());
sb.append("*))");
}
// Use filter to get matching resources.
Resource[] resources = m_repoAdmin.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;
out.print(name);
if (pc.isVerbose() && revisions[0].getPresentationName() != null)
{
out.print(" [" + revisions[0].getSymbolicName() + "]");
}
out.print(" (");
int revIdx = 0;
do
{
if (revIdx > 0)
{
out.print(", ");
}
out.print(revisions[revIdx].getVersion());
revIdx++;
}
while (pc.isVerbose() && (revIdx < revisions.length));
if (!pc.isVerbose() && (revisions.length > 1))
{
out.print(", ...");
}
out.println(")");
}
if ((resources == null) || (resources.length == 0))
{
out.println("No matching bundles.");
}
}
private void info(
String commandLine, String command, PrintStream out, PrintStream err)
throws IOException, InvalidSyntaxException
{
ParsedCommand pc = parseInfo(commandLine);
for (int cmdIdx = 0; (pc != null) && (cmdIdx < pc.getTargetCount()); cmdIdx++)
{
// Find the target's bundle resource.
Resource[] resources = searchRepository(pc.getTargetId(cmdIdx), pc.getTargetVersion(cmdIdx));
if (resources == null)
{
err.println("Unknown bundle and/or version: "
+ pc.getTargetId(cmdIdx));
}
else
{
for (int resIdx = 0; resIdx < resources.length; resIdx++)
{
if (resIdx > 0)
{
out.println("");
}
printResource(out, resources[resIdx]);
}
}
}
}
private void deploy(
String commandLine, String command, PrintStream out, PrintStream err)
throws IOException, InvalidSyntaxException
{
ParsedCommand pc = parseInstallStart(commandLine);
_deploy(pc, command, out, err);
}
private void _deploy(
ParsedCommand pc, String command, PrintStream out, PrintStream err)
throws IOException, InvalidSyntaxException
{
org.apache.felix.bundlerepository.Resolver resolver = m_repoAdmin.resolver();
for (int i = 0; (pc != null) && (i < pc.getTargetCount()); i++)
{
// Find the target's bundle resource.
Resource resource = selectNewestVersion(
searchRepository(pc.getTargetId(i), pc.getTargetVersion(i)));
if (resource != null)
{
resolver.add(resource);
}
else
{
err.println("Unknown bundle - " + pc.getTargetId(i));
}
}
if ((resolver.getAddedResources() != null) &&
(resolver.getAddedResources().length > 0))
{
if (resolver.resolve())
{
out.println("Target resource(s):");
printUnderline(out, 19);
Resource[] resources = resolver.getAddedResources();
for (int resIdx = 0; (resources != null) && (resIdx < resources.length); resIdx++)
{
out.println(" " + resources[resIdx].getPresentationName()
+ " (" + resources[resIdx].getVersion() + ")");
}
resources = resolver.getRequiredResources();
if ((resources != null) && (resources.length > 0))
{
out.println("\nRequired resource(s):");
printUnderline(out, 21);
for (int resIdx = 0; resIdx < resources.length; resIdx++)
{
out.println(" " + resources[resIdx].getPresentationName()
+ " (" + resources[resIdx].getVersion() + ")");
}
}
resources = resolver.getOptionalResources();
if ((resources != null) && (resources.length > 0))
{
out.println("\nOptional resource(s):");
printUnderline(out, 21);
for (int resIdx = 0; resIdx < resources.length; resIdx++)
{
out.println(" " + resources[resIdx].getPresentationName()
+ " (" + resources[resIdx].getVersion() + ")");
}
}
try
{
out.print("\nDeploying...");
resolver.deploy(command.equals(START_CMD) ? Resolver.START : 0);
out.println("done.");
}
catch (IllegalStateException ex)
{
err.println(ex);
}
}
else
{
Reason[] reqs = resolver.getUnsatisfiedRequirements();
if ((reqs != null) && (reqs.length > 0))
{
out.println("Unsatisfied requirement(s):");
printUnderline(out, 27);
for (int reqIdx = 0; reqIdx < reqs.length; reqIdx++)
{
out.println(" " + reqs[reqIdx].getRequirement().getFilter());
out.println(" " + reqs[reqIdx].getResource().getPresentationName());
}
}
else
{
out.println("Could not resolve targets.");
}
}
}
}
private void source(
String commandLine, String command, PrintStream out, PrintStream err)
throws IOException, InvalidSyntaxException
{
// Parse the command line to get all local targets to update.
ParsedCommand pc = parseSource(commandLine);
for (int i = 0; i < pc.getTargetCount(); i++)
{
Resource resource = selectNewestVersion(
searchRepository(pc.getTargetId(i), pc.getTargetVersion(i)));
if (resource == null)
{
err.println("Unknown bundle and/or version: "
+ pc.getTargetId(i));
}
else
{
String srcURI = (String) resource.getProperties().get(Resource.SOURCE_URI);
if (srcURI != null)
{
FileUtil.downloadSource(
out, err, new URL(srcURI), pc.getDirectory(), pc.isExtract());
}
else
{
err.println("Missing source URL: " + pc.getTargetId(i));
}
}
}
}
private void javadoc(
String commandLine, String command, PrintStream out, PrintStream err)
throws IOException, InvalidSyntaxException
{
// Parse the command line to get all local targets to update.
ParsedCommand pc = parseSource(commandLine);
for (int i = 0; i < pc.getTargetCount(); i++)
{
Resource resource = selectNewestVersion(
searchRepository(pc.getTargetId(i), pc.getTargetVersion(i)));
if (resource == null)
{
err.println("Unknown bundle and/or version: "
+ pc.getTargetId(i));
}
else
{
URL docURL = (URL) resource.getProperties().get("javadoc");
if (docURL != null)
{
FileUtil.downloadSource(
out, err, docURL, pc.getDirectory(), pc.isExtract());
}
else
{
err.println("Missing javadoc URL: " + pc.getTargetId(i));
}
}
}
}
private Resource[] searchRepository(String targetId, String targetVersion) throws InvalidSyntaxException
{
// Try to see if the targetId is a bundle ID.
try
{
Bundle bundle = m_context.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 m_repoAdmin.discoverResources(sb.toString());
}
public 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)
{
printUnderline(out, resource.getPresentationName().length());
out.println(resource.getPresentationName());
printUnderline(out, 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 void printUnderline(PrintStream out, int length)
{
for (int i = 0; i < length; i++)
{
out.print('-');
}
out.println("");
}
private ParsedCommand parseList(String commandLine)
throws IOException, InvalidSyntaxException
{
// The command line for list will be something like:
// obr list -v token token
// Create a stream tokenizer for the command line string,
StringReader sr = new StringReader(commandLine);
StreamTokenizer tokenizer = new StreamTokenizer(sr);
tokenizer.resetSyntax();
tokenizer.quoteChar('\'');
tokenizer.quoteChar('\"');
tokenizer.whitespaceChars('\u0000', '\u0020');
tokenizer.wordChars('A', 'Z');
tokenizer.wordChars('a', 'z');
tokenizer.wordChars('0', '9');
tokenizer.wordChars('\u00A0', '\u00FF');
tokenizer.wordChars('.', '.');
tokenizer.wordChars('-', '-');
tokenizer.wordChars('_', '_');
// Ignore the invoking command name and the OBR command.
int type = tokenizer.nextToken();
type = tokenizer.nextToken();
int EOF = 1;
int SWITCH = 2;
int TOKEN = 4;
// Construct an install record.
ParsedCommand pc = new ParsedCommand();
String tokens = null;
// The state machine starts by expecting either a
// SWITCH or a DIRECTORY.
int expecting = (SWITCH | TOKEN | EOF);
while (true)
{
// Get the next token type.
type = tokenizer.nextToken();
switch (type)
{
// EOF received.
case StreamTokenizer.TT_EOF:
// Error if we weren't expecting EOF.
if ((expecting & EOF) == 0)
{
throw new InvalidSyntaxException(
"Expecting more arguments.", null);
}
// Add current target if there is one.
if (tokens != null)
{
pc.setTokens(tokens);
}
// Return cleanly.
return pc;
// WORD or quoted WORD received.
case StreamTokenizer.TT_WORD:
case '\'':
case '\"':
// If we are expecting a command SWITCH and the token
// equals a command SWITCH, then record it.
if (((expecting & SWITCH) > 0) && tokenizer.sval.equals(VERBOSE_SWITCH))
{
pc.setVerbose(true);
expecting = (TOKEN | EOF);
}
// If we are expecting a target, the record it.
else if ((expecting & TOKEN) > 0)
{
// Add a space in between tokens.
if (tokens == null)
{
tokens = "";
}
else
{
tokens += " ";
}
// Append to the current token.
tokens += tokenizer.sval;
expecting = (EOF | TOKEN);
}
else
{
throw new InvalidSyntaxException(
"Not expecting '" + tokenizer.sval + "'.", null);
}
break;
}
}
}
private ParsedCommand parseInfo(String commandLine)
throws IOException, InvalidSyntaxException
{
// Create a stream tokenizer for the command line string,
// since the syntax for install/start is more sophisticated.
StringReader sr = new StringReader(commandLine);
StreamTokenizer tokenizer = new StreamTokenizer(sr);
tokenizer.resetSyntax();
tokenizer.quoteChar('\'');
tokenizer.quoteChar('\"');
tokenizer.whitespaceChars('\u0000', '\u0020');
tokenizer.wordChars('A', 'Z');
tokenizer.wordChars('a', 'z');
tokenizer.wordChars('0', '9');
tokenizer.wordChars('\u00A0', '\u00FF');
tokenizer.wordChars('.', '.');
tokenizer.wordChars('-', '-');
tokenizer.wordChars('_', '_');
// Ignore the invoking command name and the OBR command.
int type = tokenizer.nextToken();
type = tokenizer.nextToken();
int EOF = 1;
int SWITCH = 2;
int TARGET = 4;
int VERSION = 8;
int VERSION_VALUE = 16;
// Construct an install record.
ParsedCommand pc = new ParsedCommand();
String currentTargetName = null;
// The state machine starts by expecting either a
// SWITCH or a TARGET.
int expecting = (TARGET);
while (true)
{
// Get the next token type.
type = tokenizer.nextToken();
switch (type)
{
// EOF received.
case StreamTokenizer.TT_EOF:
// Error if we weren't expecting EOF.
if ((expecting & EOF) == 0)
{
throw new InvalidSyntaxException(
"Expecting more arguments.", null);
}
// Add current target if there is one.
if (currentTargetName != null)
{
pc.addTarget(currentTargetName, null);
}
// Return cleanly.
return pc;
// WORD or quoted WORD received.
case StreamTokenizer.TT_WORD:
case '\'':
case '\"':
// If we are expecting a target, the record it.
if ((expecting & TARGET) > 0)
{
// Add current target if there is one.
if (currentTargetName != null)
{
pc.addTarget(currentTargetName, null);
}
// Set the new target as the current target.
currentTargetName = tokenizer.sval;
expecting = (EOF | TARGET | VERSION);
}
else if ((expecting & VERSION_VALUE) > 0)
{
pc.addTarget(currentTargetName, tokenizer.sval);
currentTargetName = null;
expecting = (EOF | TARGET);
}
else
{
throw new InvalidSyntaxException(
"Not expecting '" + tokenizer.sval + "'.", null);
}
break;
// Version separator character received.
case ';':
// Error if we weren't expecting the version separator.
if ((expecting & VERSION) == 0)
{
throw new InvalidSyntaxException(
"Not expecting version.", null);
}
// Otherwise, we will only expect a version value next.
expecting = (VERSION_VALUE);
break;
}
}
}
private ParsedCommand parseInstallStart(String commandLine)
throws IOException, InvalidSyntaxException
{
// Create a stream tokenizer for the command line string,
// since the syntax for install/start is more sophisticated.
StringReader sr = new StringReader(commandLine);
StreamTokenizer tokenizer = new StreamTokenizer(sr);
tokenizer.resetSyntax();
tokenizer.quoteChar('\'');
tokenizer.quoteChar('\"');
tokenizer.whitespaceChars('\u0000', '\u0020');
tokenizer.wordChars('A', 'Z');
tokenizer.wordChars('a', 'z');
tokenizer.wordChars('0', '9');
tokenizer.wordChars('\u00A0', '\u00FF');
tokenizer.wordChars('.', '.');
tokenizer.wordChars('-', '-');
tokenizer.wordChars('_', '_');
// Ignore the invoking command name and the OBR command.
int type = tokenizer.nextToken();
type = tokenizer.nextToken();
int EOF = 1;
int SWITCH = 2;
int TARGET = 4;
int VERSION = 8;
int VERSION_VALUE = 16;
// Construct an install record.
ParsedCommand pc = new ParsedCommand();
String currentTargetName = null;
// The state machine starts by expecting either a
// SWITCH or a TARGET.
int expecting = (SWITCH | TARGET);
while (true)
{
// Get the next token type.
type = tokenizer.nextToken();
switch (type)
{
// EOF received.
case StreamTokenizer.TT_EOF:
// Error if we weren't expecting EOF.
if ((expecting & EOF) == 0)
{
throw new InvalidSyntaxException(
"Expecting more arguments.", null);
}
// Add current target if there is one.
if (currentTargetName != null)
{
pc.addTarget(currentTargetName, null);
}
// Return cleanly.
return pc;
// WORD or quoted WORD received.
case StreamTokenizer.TT_WORD:
case '\'':
case '\"':
// If we are expecting a target, the record it.
if ((expecting & TARGET) > 0)
{
// Add current target if there is one.
if (currentTargetName != null)
{
pc.addTarget(currentTargetName, null);
}
// Set the new target as the current target.
currentTargetName = tokenizer.sval;
expecting = (EOF | TARGET | VERSION);
}
else if ((expecting & VERSION_VALUE) > 0)
{
pc.addTarget(currentTargetName, tokenizer.sval);
currentTargetName = null;
expecting = (EOF | TARGET);
}
else
{
throw new InvalidSyntaxException(
"Not expecting '" + tokenizer.sval + "'.", null);
}
break;
// Version separator character received.
case ';':
// Error if we weren't expecting the version separator.
if ((expecting & VERSION) == 0)
{
throw new InvalidSyntaxException(
"Not expecting version.", null);
}
// Otherwise, we will only expect a version value next.
expecting = (VERSION_VALUE);
break;
}
}
}
private ParsedCommand parseSource(String commandLine)
throws IOException, InvalidSyntaxException
{
// Create a stream tokenizer for the command line string,
// since the syntax for install/start is more sophisticated.
StringReader sr = new StringReader(commandLine);
StreamTokenizer tokenizer = new StreamTokenizer(sr);
tokenizer.resetSyntax();
tokenizer.quoteChar('\'');
tokenizer.quoteChar('\"');
tokenizer.whitespaceChars('\u0000', '\u0020');
tokenizer.wordChars('A', 'Z');
tokenizer.wordChars('a', 'z');
tokenizer.wordChars('0', '9');
tokenizer.wordChars('\u00A0', '\u00FF');
tokenizer.wordChars('.', '.');
tokenizer.wordChars('-', '-');
tokenizer.wordChars('_', '_');
tokenizer.wordChars('/', '/');
tokenizer.wordChars('\\', '\\');
tokenizer.wordChars(':', ':');
// Ignore the invoking command name and the OBR command.
int type = tokenizer.nextToken();
type = tokenizer.nextToken();
int EOF = 1;
int SWITCH = 2;
int DIRECTORY = 4;
int TARGET = 8;
int VERSION = 16;
int VERSION_VALUE = 32;
// Construct an install record.
ParsedCommand pc = new ParsedCommand();
String currentTargetName = null;
// The state machine starts by expecting either a
// SWITCH or a DIRECTORY.
int expecting = (SWITCH | DIRECTORY);
while (true)
{
// Get the next token type.
type = tokenizer.nextToken();
switch (type)
{
// EOF received.
case StreamTokenizer.TT_EOF:
// Error if we weren't expecting EOF.
if ((expecting & EOF) == 0)
{
throw new InvalidSyntaxException(
"Expecting more arguments.", null);
}
// Add current target if there is one.
if (currentTargetName != null)
{
pc.addTarget(currentTargetName, null);
}
// Return cleanly.
return pc;
// WORD or quoted WORD received.
case StreamTokenizer.TT_WORD:
case '\'':
case '\"':
// If we are expecting a command SWITCH and the token
// equals a command SWITCH, then record it.
if (((expecting & SWITCH) > 0) && tokenizer.sval.equals(EXTRACT_SWITCH))
{
pc.setExtract(true);
expecting = (DIRECTORY);
}
// If we are expecting a directory, the record it.
else if ((expecting & DIRECTORY) > 0)
{
// Set the directory for the command.
pc.setDirectory(tokenizer.sval);
expecting = (TARGET);
}
// If we are expecting a target, the record it.
else if ((expecting & TARGET) > 0)
{
// Add current target if there is one.
if (currentTargetName != null)
{
pc.addTarget(currentTargetName, null);
}
// Set the new target as the current target.
currentTargetName = tokenizer.sval;
expecting = (EOF | TARGET | VERSION);
}
else if ((expecting & VERSION_VALUE) > 0)
{
pc.addTarget(currentTargetName, tokenizer.sval);
currentTargetName = null;
expecting = (EOF | TARGET);
}
else
{
throw new InvalidSyntaxException(
"Not expecting '" + tokenizer.sval + "'.", null);
}
break;
// Version separator character received.
case ';':
// Error if we weren't expecting the version separator.
if ((expecting & VERSION) == 0)
{
throw new InvalidSyntaxException(
"Not expecting version.", null);
}
// Otherwise, we will only expect a version value next.
expecting = (VERSION_VALUE);
break;
}
}
}
private void help(PrintStream out, StringTokenizer st)
{
String command = HELP_CMD;
if (st.hasMoreTokens())
{
command = st.nextToken();
}
if (command.equals(ADDURL_CMD))
{
out.println("");
out.println("obr " + ADDURL_CMD + " <repository-url> ...");
out.println("");
out.println(
"This command adds the space-delimited list of repository URLs to\n" +
"the repository service.");
out.println("");
}
else if (command.equals(REFRESHURL_CMD))
{
out.println("");
out.println("obr " + REFRESHURL_CMD + " <repository-url> ...");
out.println("");
out.println(
"This command refreshes the space-delimited list of repository URLs\n" +
"within the repository service.\n" +
"(The command internally removes and adds the specified URLs from the\n" +
"repository service.)");
out.println("");
}
else if (command.equals(REMOVEURL_CMD))
{
out.println("");
out.println("obr " + REMOVEURL_CMD + " <repository-url> ...");
out.println("");
out.println(
"This command removes the space-delimited list of repository URLs\n" +
"from the repository service.");
out.println("");
}
else if (command.equals(LISTURL_CMD))
{
out.println("");
out.println("obr " + LISTURL_CMD);
out.println("");
out.println(
"This command displays the repository URLs currently associated\n" +
"with the repository service.");
out.println("");
}
else if (command.equals(LIST_CMD))
{
out.println("");
out.println("obr " + LIST_CMD
+ " [" + VERBOSE_SWITCH + "] [<string> ...]");
out.println("");
out.println(
"This command lists bundles available in the bundle repository.\n" +
"If no arguments are specified, then all available bundles are\n" +
"listed, otherwise any arguments are concatenated with spaces\n" +
"and used as a substring filter on the bundle names. By default,\n" +
"only the most recent version of each artifact is shown. To list\n" +
"all available versions use the \"" + VERBOSE_SWITCH + "\" switch.");
out.println("");
}
else if (command.equals(INFO_CMD))
{
out.println("");
out.println("obr " + INFO_CMD
+ " <bundle-name>|<bundle-symbolic-name>|<bundle-id>[;<version>] ...");
out.println("");
out.println(
"This command displays the meta-data for the specified bundles.\n" +
"If a bundle's name contains spaces, then it must be surrounded\n" +
"by quotes. It is also possible to specify a precise version\n" +
"if more than one version exists, such as:\n" +
"\n" +
" obr info \"Bundle Repository\";1.0.0\n" +
"\n" +
"The above example retrieves the meta-data for version \"1.0.0\"\n" +
"of the bundle named \"Bundle Repository\".");
out.println("");
}
else if (command.equals(DEPLOY_CMD))
{
out.println("");
out.println("obr " + DEPLOY_CMD
+ " <bundle-name>|<bundle-symbolic-name>|<bundle-id>[;<version>] ... ");
out.println("");
out.println(
"This command tries to install or update the specified bundles\n" +
"and all of their dependencies. You can specify either the bundle\n" +
"name or the bundle identifier. If a bundle's name contains spaces,\n" +
"then it must be surrounded by quotes. It is also possible to\n" +
"specify a precise version if more than one version exists, such as:\n" +
"\n" +
" obr deploy \"Bundle Repository\";1.0.0\n" +
"\n" +
"For the above example, if version \"1.0.0\" of \"Bundle Repository\" is\n" +
"already installed locally, then the command will attempt to update it\n" +
"and all of its dependencies; otherwise, the command will install it\n" +
"and all of its dependencies.");
out.println("");
}
else if (command.equals(START_CMD))
{
out.println("");
out.println("obr " + START_CMD
+ " <bundle-name>|<bundle-symbolic-name>|<bundle-id>[;<version>] ...");
out.println("");
out.println(
"This command installs and starts the specified bundles and all\n" +
"of their dependencies. If a bundle's name contains spaces, then\n" +
"it must be surrounded by quotes. If a specified bundle is already\n" + "installed, then this command has no effect. It is also possible\n" + "to specify a precise version if more than one version exists,\n" + "such as:\n" +
"\n" +
" obr start \"Bundle Repository\";1.0.0\n" +
"\n" +
"The above example installs and starts version \"1.0.0\" of the\n" +
"bundle named \"Bundle Repository\" and its dependencies.");
out.println("");
}
else if (command.equals(SOURCE_CMD))
{
out.println("");
out.println("obr " + SOURCE_CMD
+ " [" + EXTRACT_SWITCH
+ "] <local-dir> <bundle-name>[;<version>] ...");
out.println("");
out.println(
"This command retrieves the source archives of the specified\n" +
"bundles and saves them to the specified local directory; use\n" +
"the \"" + EXTRACT_SWITCH + "\" switch to automatically extract the source archives.\n" +
"If a bundle name contains spaces, then it must be surrounded\n" +
"by quotes. It is also possible to specify a precise version if\n" + "more than one version exists, such as:\n" +
"\n" +
" obr source /home/rickhall/tmp \"Bundle Repository\";1.0.0\n" +
"\n" +
"The above example retrieves the source archive of version \"1.0.0\"\n" +
"of the bundle named \"Bundle Repository\" and saves it to the\n" +
"specified local directory.");
out.println("");
}
else if (command.equals(JAVADOC_CMD))
{
out.println("");
out.println("obr " + JAVADOC_CMD
+ " [" + EXTRACT_SWITCH
+ "] <local-dir> <bundle-name>[;<version>] ...");
out.println("");
out.println(
"This command retrieves the javadoc archives of the specified\n" +
"bundles and saves them to the specified local directory; use\n" +
"the \"" + EXTRACT_SWITCH + "\" switch to automatically extract the javadoc archives.\n" +
"If a bundle name contains spaces, then it must be surrounded\n" +
"by quotes. It is also possible to specify a precise version if\n" + "more than one version exists, such as:\n" +
"\n" +
" obr javadoc /home/rickhall/tmp \"Bundle Repository\";1.0.0\n" +
"\n" +
"The above example retrieves the javadoc archive of version \"1.0.0\"\n" +
"of the bundle named \"Bundle Repository\" and saves it to the\n" +
"specified local directory.");
out.println("");
}
else
{
out.println("obr " + HELP_CMD
+ " [" + ADDURL_CMD
+ " | " + REMOVEURL_CMD
+ " | " + LISTURL_CMD
+ " | " + LIST_CMD
+ " | " + INFO_CMD
+ " | " + DEPLOY_CMD + " | " + START_CMD
+ " | " + SOURCE_CMD + " | " + JAVADOC_CMD + "]");
out.println("obr " + ADDURL_CMD + " [<repository-file-url> ...]");
out.println("obr " + REFRESHURL_CMD + " [<repository-file-url> ...]");
out.println("obr " + REMOVEURL_CMD + " [<repository-file-url> ...]");
out.println("obr " + LISTURL_CMD);
out.println("obr " + LIST_CMD + " [" + VERBOSE_SWITCH + "] [<string> ...]");
out.println("obr " + INFO_CMD
+ " <bundle-name>|<bundle-symbolic-name>|<bundle-id>[;<version>] ...");
out.println("obr " + DEPLOY_CMD
+ " <bundle-name>|<bundle-symbolic-name>|<bundle-id>[;<version>] ...");
out.println("obr " + START_CMD
+ " <bundle-name>|<bundle-symbolic-name>|<bundle-id>[;<version>] ...");
out.println("obr " + SOURCE_CMD
+ " [" + EXTRACT_SWITCH
+ "] <local-dir> <bundle-name>[;<version>] ...");
out.println("obr " + JAVADOC_CMD
+ " [" + EXTRACT_SWITCH
+ "] <local-dir> <bundle-name>[;<version>] ...");
}
}
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;
}
private static class ParsedCommand
{
private static final int NAME_IDX = 0;
private static final int VERSION_IDX = 1;
private boolean m_isResolve = true;
private boolean m_isCheck = false;
private boolean m_isExtract = false;
private boolean m_isVerbose = false;
private String m_tokens = null;
private String m_dir = null;
private String[][] m_targets = new String[0][];
public boolean isResolve()
{
return m_isResolve;
}
public void setResolve(boolean b)
{
m_isResolve = b;
}
public boolean isCheck()
{
return m_isCheck;
}
public void setCheck(boolean b)
{
m_isCheck = b;
}
public boolean isExtract()
{
return m_isExtract;
}
public void setExtract(boolean b)
{
m_isExtract = b;
}
public boolean isVerbose()
{
return m_isVerbose;
}
public void setVerbose(boolean b)
{
m_isVerbose = b;
}
public String getTokens()
{
return m_tokens;
}
public void setTokens(String s)
{
m_tokens = s;
}
public String getDirectory()
{
return m_dir;
}
public void setDirectory(String s)
{
m_dir = s;
}
public int getTargetCount()
{
return m_targets.length;
}
public String getTargetId(int i)
{
if ((i < 0) || (i >= getTargetCount()))
{
return null;
}
return m_targets[i][NAME_IDX];
}
public String getTargetVersion(int i)
{
if ((i < 0) || (i >= getTargetCount()))
{
return null;
}
return m_targets[i][VERSION_IDX];
}
public void addTarget(String name, String version)
{
String[][] newTargets = new String[m_targets.length + 1][];
System.arraycopy(m_targets, 0, newTargets, 0, m_targets.length);
newTargets[m_targets.length] = new String[] { name, version };
m_targets = newTargets;
}
}
}