You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ri...@apache.org on 2005/08/16 20:34:41 UTC
svn commit: r233031 [2/21] - in /incubator/oscar/trunk: ./ etc/ lib/ src/
src/org/ src/org/apache/ src/org/apache/osgi/ src/org/apache/osgi/bundle/
src/org/apache/osgi/bundle/bundlerepository/
src/org/apache/osgi/bundle/bundlerepository/kxmlsax/ src/or...
Added: incubator/oscar/trunk/src/org/apache/osgi/bundle/bundlerepository/ObrCommandImpl.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/bundle/bundlerepository/ObrCommandImpl.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/bundle/bundlerepository/ObrCommandImpl.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/bundle/bundlerepository/ObrCommandImpl.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,1374 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.osgi.bundle.bundlerepository;
+
+import java.io.*;
+import java.util.*;
+
+import org.apache.osgi.service.bundlerepository.BundleRecord;
+import org.apache.osgi.service.bundlerepository.BundleRepository;
+import org.apache.osgi.service.shell.Command;
+import org.osgi.framework.*;
+
+public class ObrCommandImpl implements Command
+{
+ private static final String HELP_CMD = "help";
+ private static final String URLS_CMD = "urls";
+ 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 INSTALL_CMD = "install";
+ private static final String START_CMD = "start";
+// private static final String UPDATE_CMD = "update";
+ private static final String SOURCE_CMD = "source";
+
+ private static final String NODEPS_SWITCH = "-nodeps";
+ private static final String CHECK_SWITCH = "-check";
+ private static final String EXTRACT_SWITCH = "-x";
+
+ private BundleContext m_context = null;
+ private BundleRepository m_repo = null;
+
+ public ObrCommandImpl(BundleContext context, BundleRepository repo)
+ {
+ m_context = context;
+ m_repo = repo;
+ }
+
+ 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(URLS_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(INSTALL_CMD) || command.equals(START_CMD))
+ {
+ install(commandLine, command, out, err);
+ }
+ else if (command.equals(UPDATE_CMD))
+ {
+ update(commandLine, command, out, err);
+ }
+*/
+ else if (command.equals(SOURCE_CMD))
+ {
+ source(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 "urls" command.
+ st.nextToken();
+
+ int count = st.countTokens();
+ String[] urls = new String[count];
+ for (int i = 0; i < count; i++)
+ {
+ urls[i] = st.nextToken();
+ }
+
+ if (count > 0)
+ {
+ m_repo.setRepositoryURLs(urls);
+ }
+ else
+ {
+ urls = m_repo.getRepositoryURLs();
+ if (urls != null)
+ {
+ for (int i = 0; i < urls.length; i++)
+ {
+ out.println(urls[i]);
+ }
+ }
+ else
+ {
+ out.println("No repository URLs are set.");
+ }
+ }
+ }
+
+ private void list(
+ String commandLine, String command, PrintStream out, PrintStream err)
+ throws IOException
+ {
+ // 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();
+
+ String substr = null;
+
+ for (type = tokenizer.nextToken();
+ type != StreamTokenizer.TT_EOF;
+ type = tokenizer.nextToken())
+ {
+ // Add a space in between tokens.
+ if (substr == null)
+ {
+ substr = "";
+ }
+ else
+ {
+ substr += " ";
+ }
+
+ if ((type == StreamTokenizer.TT_WORD) ||
+ (type == '\'') || (type == '"'))
+ {
+ substr += tokenizer.sval.toLowerCase();
+ }
+ }
+
+ boolean found = false;
+ BundleRecord[] records = m_repo.getBundleRecords();
+ for (int recIdx = 0; recIdx < records.length; recIdx++)
+ {
+ String name = (String)
+ records[recIdx].getAttribute(BundleRecord.BUNDLE_NAME);
+ String symName = (String)
+ records[recIdx].getAttribute(BundleRecord.BUNDLE_SYMBOLICNAME);
+ if ((substr == null) ||
+ ((name != null) && (name.toLowerCase().indexOf(substr) >= 0)) ||
+ ((symName != null) && (symName.toLowerCase().indexOf(substr) >= 0)))
+ {
+ found = true;
+ String version =
+ (String) records[recIdx].getAttribute(BundleRecord.BUNDLE_VERSION);
+ if (version != null)
+ {
+ out.println(name + " (" + version + ")");
+ }
+ else
+ {
+ out.println(name);
+ }
+ }
+ }
+
+ if (!found)
+ {
+ 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 i = 0; (pc != null) && (i < pc.getTargetCount()); i++)
+ {
+ BundleRecord[] records = searchRepository(
+ pc.getTargetId(i), pc.getTargetVersion(i));
+ if (records == null)
+ {
+ err.println("Unknown bundle and/or version: "
+ + pc.getTargetId(i));
+ }
+ else if (records.length > 1)
+ {
+ err.println("More than one version exists: "
+ + pc.getTargetId(i));
+ }
+ else
+ {
+ records[0].printAttributes(out);
+ }
+ }
+ }
+
+ 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
+ {
+ for (int i = 0; (pc != null) && (i < pc.getTargetCount()); i++)
+ {
+ // Find the target's bundle record.
+ BundleRecord record = selectNewestVersion(
+ searchRepository(pc.getTargetId(i), pc.getTargetVersion(i)));
+ if (record != null)
+ {
+ m_repo.deployBundle(
+ out, // Output stream.
+ err, // Error stream.
+ (String) record.getAttribute(BundleRecord.BUNDLE_SYMBOLICNAME),
+ Util.parseVersionString((String)record.getAttribute(BundleRecord.BUNDLE_VERSION)),
+ pc.isResolve(), // Resolve dependencies.
+ command.equals(START_CMD)); // Start.
+ }
+ else
+ {
+ err.println("Unknown bundle or amiguous version: "
+ + pc.getTargetId(i));
+ }
+ }
+ }
+/*
+ private void install(
+ String commandLine, String command, PrintStream out, PrintStream err)
+ throws IOException, InvalidSyntaxException
+ {
+ // Parse the command line to get all local targets to install.
+ ParsedCommand pc = parseInstallStart(commandLine);
+
+ // Loop through each local target and try to find
+ // the corresponding bundle record from the repository.
+ for (int targetIdx = 0;
+ (pc != null) && (targetIdx < pc.getTargetCount());
+ targetIdx++)
+ {
+ // Get the current target's name and version.
+ String targetName = pc.getTargetId(targetIdx);
+ String targetVersionString = pc.getTargetVersion(targetIdx);
+
+ // Make sure the bundle is not already installed.
+ Bundle bundle = findLocalBundle(targetName, targetVersionString);
+ if (bundle == null)
+ {
+ _deploy(pc, command, out, err);
+ }
+ else
+ {
+ err.println("Already installed: " + targetName);
+ }
+ }
+ }
+
+ private void update(
+ String commandLine, String command, PrintStream out, PrintStream err)
+ throws IOException, InvalidSyntaxException
+ {
+ // Parse the command line to get all local targets to update.
+ ParsedCommand pc = parseUpdate(commandLine);
+
+ if (pc.isCheck())
+ {
+ updateCheck(out, err);
+ }
+ else
+ {
+ // Loop through each local target and try to find
+ // the corresponding bundle record from the repository.
+ for (int targetIdx = 0;
+ (pc != null) && (targetIdx < pc.getTargetCount());
+ targetIdx++)
+ {
+ // Get the current target's name and version.
+ String targetName = pc.getTargetId(targetIdx);
+ String targetVersionString = pc.getTargetVersion(targetIdx);
+
+ // Make sure the bundle is not already installed.
+ Bundle bundle = findLocalBundle(targetName, targetVersionString);
+ if (bundle != null)
+ {
+ _deploy(pc, command, out, err);
+ }
+ else
+ {
+ err.println("Not installed: " + targetName);
+ }
+ }
+ }
+ }
+
+ private void updateCheck(PrintStream out, PrintStream err)
+ throws IOException
+ {
+ Bundle[] bundles = m_context.getBundles();
+
+ // Loop through each local target and try to find
+ // the corresponding locally installed bundle.
+ for (int bundleIdx = 0;
+ (bundles != null) && (bundleIdx < bundles.length);
+ bundleIdx++)
+ {
+ // Ignore the system bundle.
+ if (bundles[bundleIdx].getBundleId() == 0)
+ {
+ continue;
+ }
+
+ // Get the local bundle's update location.
+ String localLoc = (String)
+ bundles[bundleIdx].getHeaders().get(Constants.BUNDLE_UPDATELOCATION);
+ if (localLoc == null)
+ {
+ // Without an update location, there is no way to
+ // check for an update, so ignore the bundle.
+ continue;
+ }
+
+ // Get the local bundle's version.
+ String localVersion = (String)
+ bundles[bundleIdx].getHeaders().get(Constants.BUNDLE_VERSION);
+ localVersion = (localVersion == null) ? "0.0.0" : localVersion;
+
+ // Get the matching repository bundle records.
+ BundleRecord[] records = m_repo.getBundleRecords(
+ (String) bundles[bundleIdx].getHeaders().get(Constants.BUNDLE_NAME));
+
+ // Loop through all records to see if there is an update.
+ for (int recordIdx = 0;
+ (records != null) && (recordIdx < records.length);
+ recordIdx++)
+ {
+ String remoteLoc = (String)
+ records[recordIdx].getAttribute(BundleRecord.BUNDLE_UPDATELOCATION);
+ if (remoteLoc == null)
+ {
+ continue;
+ }
+
+ // If the update locations are equal, then compare versions.
+ if (remoteLoc.equals(localLoc))
+ {
+ String remoteVersion = (String)
+ records[recordIdx].getAttribute(BundleRecord.BUNDLE_VERSION);
+ if (remoteVersion != null)
+ {
+ int result = Util.compareVersion(
+ Util.parseVersionString(remoteVersion),
+ Util.parseVersionString(localVersion));
+ if (result > 0)
+ {
+ out.println(
+ records[recordIdx].getAttribute(BundleRecord.BUNDLE_NAME)
+ + " update available.");
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+*/
+ 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++)
+ {
+ BundleRecord[] records =
+ searchRepository(pc.getTargetId(i), pc.getTargetVersion(i));
+ if (records == null)
+ {
+ err.println("Unknown bundle and/or version: "
+ + pc.getTargetId(i));
+ }
+ else if (records.length > 1)
+ {
+ err.println("More than one version exists: "
+ + pc.getTargetId(i));
+ }
+ else
+ {
+ String srcURL = (String)
+ records[0].getAttribute(BundleRecord.BUNDLE_SOURCEURL);
+ if (srcURL != null)
+ {
+ FileUtil.downloadSource(
+ out, err, srcURL, pc.getDirectory(), pc.isExtract());
+ }
+ else
+ {
+ err.println("Missing source URL: " + pc.getTargetId(i));
+ }
+ }
+ }
+ }
+
+ private BundleRecord[] searchRepository(String targetId, String targetVersion)
+ {
+ // The targetId may be a bundle name or a bundle symbolic name.
+ // Query for symbolic name first, since it is more specific. If
+ // that can't be found, then compare bundle names.
+ BundleRecord[] records = null;
+ if (targetVersion != null)
+ {
+ BundleRecord record = m_repo.getBundleRecord(
+ targetId, Util.parseVersionString(targetVersion));
+ if (record != null)
+ {
+ records = new BundleRecord[] { record };
+ }
+ }
+ else
+ {
+ records = m_repo.getBundleRecords(targetId);
+ }
+
+ if (records == null)
+ {
+ List recordList = new ArrayList();
+ records = m_repo.getBundleRecords();
+ for (int i = 0; (records != null) && (i < records.length); i++)
+ {
+ if (targetId.compareToIgnoreCase((String)
+ records[i].getAttribute(BundleRecord.BUNDLE_NAME)) == 0)
+ {
+ int[] v1 = Util.parseVersionString(targetVersion);
+ int[] v2 = Util.parseVersionString((String)
+ records[i].getAttribute(BundleRecord.BUNDLE_VERSION));
+ if ((targetVersion == null) ||
+ ((targetVersion != null) && (Util.compareVersion(v1, v2) == 0)))
+ {
+ recordList.add(records[i]);
+ }
+ }
+ }
+ records = (recordList.size() == 0)
+ ? null
+ : (BundleRecord[]) recordList.toArray(new BundleRecord[recordList.size()]);
+ }
+
+ return records;
+ }
+
+ public BundleRecord selectNewestVersion(BundleRecord[] records)
+ {
+ int idx = -1;
+ int[] v = null;
+ for (int i = 0; (records != null) && (i < records.length); i++)
+ {
+ if (i == 0)
+ {
+ idx = 0;
+ v = Util.parseVersionString((String)
+ records[i].getAttribute(BundleRecord.BUNDLE_VERSION));
+ }
+ else
+ {
+ int[] vtmp = Util.parseVersionString((String)
+ records[i].getAttribute(BundleRecord.BUNDLE_VERSION));
+ if (Util.compareVersion(vtmp, v) > 0)
+ {
+ idx = i;
+ v = vtmp;
+ }
+ }
+ }
+
+ return (idx < 0) ? null : records[idx];
+ }
+
+ private Bundle findLocalBundle(String name, String versionString)
+ {
+ Bundle bundle = null;
+
+ // Get the name only if there is no version, but error
+ // if there are multiple matches for the same name.
+ if (versionString == null)
+ {
+ // Perhaps the target name is a bundle ID and
+ // not a name, so try to interpret as a long.
+ try
+ {
+ bundle = m_context.getBundle(Long.parseLong(name));
+ }
+ catch (NumberFormatException ex)
+ {
+ // The bundle is not a number, so look for a local
+ // bundle with the same name.
+ Bundle[] matchingBundles = findLocalBundlesBySymbolicName(name);
+
+ // If only one matches, then select is.
+ if (matchingBundles.length == 1)
+ {
+ bundle = matchingBundles[0];
+ }
+ }
+ }
+ else
+ {
+ // Find the local bundle by name and version.
+ bundle = findLocalBundleByVersion(
+ name, Util.parseVersionString(versionString));
+ }
+
+ return bundle;
+ }
+
+ private Bundle findLocalBundleByVersion(String symName, int[] version)
+ {
+ // Get bundles with matching name.
+ Bundle[] targets = findLocalBundlesBySymbolicName(symName);
+
+ // Find bundle with matching version.
+ if (targets.length > 0)
+ {
+ for (int i = 0; i < targets.length; i++)
+ {
+ String targetName = (String)
+ targets[i].getHeaders().get(BundleRecord.BUNDLE_SYMBOLICNAME);
+ int[] targetVersion = Util.parseVersionString((String)
+ targets[i].getHeaders().get(BundleRecord.BUNDLE_VERSION));
+
+ if ((targetName != null) &&
+ targetName.equalsIgnoreCase(symName) &&
+ (Util.compareVersion(targetVersion, version) == 0))
+ {
+ return targets[i];
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private Bundle[] findLocalBundlesBySymbolicName(String symName)
+ {
+ // Get local bundles.
+ Bundle[] bundles = m_context.getBundles();
+
+ // Find bundles with matching name.
+ Bundle[] targets = new Bundle[0];
+ for (int i = 0; i < bundles.length; i++)
+ {
+ String targetName = (String)
+ bundles[i].getHeaders().get(BundleRecord.BUNDLE_SYMBOLICNAME);
+ if (targetName == null)
+ {
+ targetName = bundles[i].getLocation();
+ }
+ if ((targetName != null) && targetName.equalsIgnoreCase(symName))
+ {
+ Bundle[] newTargets = new Bundle[targets.length + 1];
+ System.arraycopy(targets, 0, newTargets, 0, targets.length);
+ newTargets[targets.length] = bundles[i];
+ targets = newTargets;
+ }
+ }
+
+ return targets;
+ }
+
+ 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 command SWITCH and the token
+ // equals a command SWITCH, then record it.
+ if (((expecting & SWITCH) > 0) && tokenizer.sval.equals(NODEPS_SWITCH))
+ {
+ pc.setResolve(false);
+ expecting = (EOF | 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 ParsedCommand parseUpdate(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 command SWITCH and the token
+ // equals a NODEPS switch, then record it.
+ if (((expecting & SWITCH) > 0) && tokenizer.sval.equals(NODEPS_SWITCH))
+ {
+ pc.setResolve(false);
+ expecting = (EOF | TARGET);
+ }
+ // If we are expecting a command SWITCH and the token
+ // equals a CHECK swithc, then record it.
+ else if (((expecting & SWITCH) > 0) && tokenizer.sval.equals(CHECK_SWITCH))
+ {
+ pc.setCheck(true);
+ expecting = (EOF);
+ }
+ // 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 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('/', '/');
+
+ // 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(URLS_CMD))
+ {
+ out.println("");
+ out.println("obr " + URLS_CMD + " [<repository-file-url> ...]");
+ out.println("");
+ out.println(
+ "This command gets or sets the URLs to the repository files\n" + "used by OBR. Specify no arguments to get the current repository\n" +
+ "URLs or specify a space-delimited list of URLs to change the\n" +
+ "URLs. Each URL should point to a file containing meta-data about\n" + "available bundles in XML format.");
+ out.println("");
+ }
+ else if (command.equals(LIST_CMD))
+ {
+ out.println("");
+ out.println("obr " + LIST_CMD + " [<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.");
+ out.println("");
+ }
+ else if (command.equals(INFO_CMD))
+ {
+ out.println("");
+ out.println("obr " + INFO_CMD
+ + " <bundle-name>[;<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
+ + " [" + NODEPS_SWITCH
+ + "] <bundle-name>[;<version>] ... | <bundle-id> ...");
+ out.println("");
+ out.println(
+ "This command tries to install or update the specified bundles\n" +
+ "and all of their dependencies by default; use the \"" + NODEPS_SWITCH + "\" switch\n" +
+ "to ignore dependencies. You can specify either the bundle name or\n" +
+ "the bundle identifier. If a bundle's name contains spaces, then\n" +
+ "it must be surrounded by quotes. It is also possible to specify a\n" + "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(INSTALL_CMD))
+ {
+ out.println("");
+ out.println("obr " + INSTALL_CMD
+ + " [" + NODEPS_SWITCH
+ + "] <bundle-name>[;<version>] ...");
+ out.println("");
+ out.println(
+ "This command installs the specified bundles and all of their\n" +
+ "dependencies by default; use the \"" + NODEPS_SWITCH + "\" switch to ignore\n" +
+ "dependencies. If a bundle's name contains spaces, then it\n" +
+ "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 install \"Bundle Repository\";1.0.0\n" +
+ "\n" +
+ "The above example installs version \"1.0.0\" of the bundle\n" +
+ "named \"Bundle Repository\" and its dependencies. ");
+ out.println("");
+ }
+*/
+ else if (command.equals(START_CMD))
+ {
+ out.println("");
+ out.println("obr " + START_CMD
+ + " [" + NODEPS_SWITCH
+ + "] <bundle-name>[;<version>] ...");
+ out.println("");
+ out.println(
+ "This command installs and starts the specified bundles and all\n" +
+ "of their dependencies by default; use the \"" + NODEPS_SWITCH + "\" switch to\n" +
+ "ignore 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(UPDATE_CMD))
+ {
+ out.println("");
+ out.println("obr " + UPDATE_CMD + " " + CHECK_SWITCH);
+ out.println("");
+ out.println("obr " + UPDATE_CMD
+ + " [" + NODEPS_SWITCH
+ + "] <bundle-name>[;<version>] ... | <bundle-id> ...");
+ out.println("");
+ out.println(
+ "The first form of the command above checks for available updates\n" + "and the second updates the specified locally installed bundles\n" +
+ "and all of their dependencies by default; use the \"" + NODEPS_SWITCH + "\" switch\n" +
+ "to ignore dependencies. You can specify either the bundle name or\n" +
+ "the bundle identifier. If a bundle's name contains spaces, then\n" +
+ "it must be surrounded by quotes. If a specified bundle is not\n" + "already installed, then this command has no effect. It is also\n" + "possible to specify a precise version if more than one version\n" + "exists, such as:\n" +
+ "\n" +
+ " obr update \"Bundle Repository\";1.0.0\n" +
+ "\n" +
+ "The above example updates version \"1.0.0\" of the bundle named\n" +
+ "\"Bundle Repository\" and its dependencies. The update command may\n" +
+ "install new bundles if the updated bundles have new 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
+ {
+ out.println("obr " + HELP_CMD
+ + " [" + URLS_CMD + " | " + LIST_CMD
+// + " | " + INFO_CMD + " | " + INSTALL_CMD
+ + " | " + INFO_CMD
+ + " | " + DEPLOY_CMD + " | " + START_CMD
+// + " | " + UPDATE_CMD + " | " + SOURCE_CMD + "]");
+ + " | " + SOURCE_CMD + "]");
+ out.println("obr " + URLS_CMD + " [<repository-file-url> ...]");
+ out.println("obr " + LIST_CMD + " [<string> ...]");
+ out.println("obr " + INFO_CMD
+ + " <bundle-name>[;<version>] ...");
+ out.println("obr " + DEPLOY_CMD
+ + " [" + NODEPS_SWITCH
+ + "] <bundle-name>[;<version>] ... | <bundle-id> ...");
+// out.println("obr " + INSTALL_CMD
+// + " [" + NODEPS_SWITCH
+// + "] <bundle-name>[;<version>] ...");
+ out.println("obr " + START_CMD
+ + " [" + NODEPS_SWITCH
+ + "] <bundle-name>[;<version>] ...");
+// out.println("obr " + UPDATE_CMD + " " + CHECK_SWITCH);
+// out.println("obr " + UPDATE_CMD
+// + " [" + NODEPS_SWITCH
+// + "] <bundle-name>[;<version>] ... | <bundle-id> ...");
+ out.println("obr " + SOURCE_CMD
+ + " [" + EXTRACT_SWITCH
+ + "] <local-dir> <bundle-name>[;<version>] ...");
+ }
+ }
+
+ 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 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 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;
+ }
+ }
+}
Added: incubator/oscar/trunk/src/org/apache/osgi/bundle/bundlerepository/R4Attribute.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/bundle/bundlerepository/R4Attribute.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/bundle/bundlerepository/R4Attribute.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/bundle/bundlerepository/R4Attribute.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.osgi.bundle.bundlerepository;
+
+import org.apache.osgi.service.bundlerepository.IAttribute;
+
+public class R4Attribute implements IAttribute
+{
+ private String m_name = "";
+ private String m_value = "";
+ private boolean m_isMandatory = false;
+
+ public R4Attribute(String name, String value, boolean isMandatory)
+ {
+ m_name = name;
+ m_value = value;
+ m_isMandatory = isMandatory;
+ }
+
+ /* (non-Javadoc)
+ * @see org.ungoverned.osgi.service.bundlerepository.Attribute#getName()
+ **/
+ public String getName()
+ {
+ return m_name;
+ }
+
+ /* (non-Javadoc)
+ * @see org.ungoverned.osgi.service.bundlerepository.Attribute#getValue()
+ **/
+ public String getValue()
+ {
+ return m_value;
+ }
+
+ /* (non-Javadoc)
+ * @see org.ungoverned.osgi.service.bundlerepository.Attribute#isMandatory()
+ **/
+ public boolean isMandatory()
+ {
+ return m_isMandatory;
+ }
+}
\ No newline at end of file
Added: incubator/oscar/trunk/src/org/apache/osgi/bundle/bundlerepository/R4Directive.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/bundle/bundlerepository/R4Directive.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/bundle/bundlerepository/R4Directive.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/bundle/bundlerepository/R4Directive.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.osgi.bundle.bundlerepository;
+
+import org.apache.osgi.service.bundlerepository.IDirective;
+
+public class R4Directive implements IDirective
+{
+ private String m_name = "";
+ private String m_value = "";
+
+ public R4Directive(String name, String value)
+ {
+ m_name = name;
+ m_value = value;
+ }
+
+ /* (non-Javadoc)
+ * @see org.ungoverned.osgi.service.bundlerepository.Directive#getName()
+ **/
+ public String getName()
+ {
+ return m_name;
+ }
+
+ /* (non-Javadoc)
+ * @see org.ungoverned.osgi.service.bundlerepository.Directive#getValue()
+ **/
+ public String getValue()
+ {
+ return m_value;
+ }
+}
\ No newline at end of file
Added: incubator/oscar/trunk/src/org/apache/osgi/bundle/bundlerepository/R4Package.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/bundle/bundlerepository/R4Package.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/bundle/bundlerepository/R4Package.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/bundle/bundlerepository/R4Package.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,501 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.osgi.bundle.bundlerepository;
+
+import java.util.*;
+
+import org.apache.osgi.service.bundlerepository.*;
+import org.osgi.framework.Constants;
+
+//
+// This class is essentially the same as the R4Package class in Felix,
+// except that I had to add the parseDelimitedString() method. These
+// two classes should be unified.
+//
+
+/**
+ * This is a simple class to encapsulate a package declaration for
+ * bundle imports and exports for the bundle repository.
+**/
+public class R4Package implements IPackage
+{
+ private String m_id = "";
+ private IDirective[] m_directives = null;
+ private IAttribute[] m_attrs = null;
+ private IVersion m_versionLow = null;
+ private IVersion m_versionHigh = null;
+ private boolean m_isOptional = false;
+
+ protected R4Package(R4Package pkg)
+ {
+ m_id = pkg.m_id;
+ m_directives = pkg.m_directives;
+ m_attrs = pkg.m_attrs;
+ m_versionLow = pkg.m_versionLow;
+ m_versionHigh = pkg.m_versionHigh;
+ m_isOptional = pkg.m_isOptional;
+ }
+
+ public R4Package(String id, IDirective[] directives, IAttribute[] attrs)
+ {
+ m_id = id;
+ m_directives = (directives == null) ? new IDirective[0] : directives;
+ m_attrs = (attrs == null) ? new IAttribute[0] : attrs;
+
+ // Find mandatory and resolution directives, if present.
+ String mandatory = "";
+ for (int i = 0; i < m_directives.length; i++)
+ {
+ if (m_directives[i].getName().equals(Constants.MANDATORY_DIRECTIVE))
+ {
+ mandatory = m_directives[i].getValue();
+ }
+ else if (m_directives[i].getName().equals(Constants.RESOLUTION_DIRECTIVE))
+ {
+ m_isOptional = m_directives[i].getValue().equals(Constants.RESOLUTION_OPTIONAL);
+ }
+ }
+
+ // Parse mandatory directive and mark specified
+ // attributes as mandatory.
+ StringTokenizer tok = new StringTokenizer(mandatory, "");
+ while (tok.hasMoreTokens())
+ {
+ // Get attribute name.
+ String attrName = tok.nextToken().trim();
+ // Find attribute and mark it as mandatory.
+ boolean found = false;
+ for (int i = 0; (!found) && (i < m_attrs.length); i++)
+ {
+ if (m_attrs[i].getName().equals(attrName))
+ {
+ m_attrs[i] = new R4Attribute(
+ m_attrs[i].getName(), m_attrs[i].getValue(), true);
+ found = true;
+ }
+ }
+ // If a specified mandatory attribute was not found,
+ // then error.
+ if (!found)
+ {
+ throw new IllegalArgumentException(
+ "Mandatory attribute '" + attrName + "' does not exist.");
+ }
+ }
+
+ // Find and parse version attribute, if present.
+ String versionInterval = "0.0.0";
+ for (int i = 0; i < m_attrs.length; i++)
+ {
+ if (m_attrs[i].getName().equals(Constants.VERSION_ATTRIBUTE) ||
+ m_attrs[i].getName().equals(Constants.PACKAGE_SPECIFICATION_VERSION))
+ {
+ // Normalize version attribute name.
+ m_attrs[i] = new R4Attribute(
+ Constants.VERSION_ATTRIBUTE, m_attrs[i].getValue(),
+ m_attrs[i].isMandatory());
+ versionInterval = m_attrs[i].getValue();
+ break;
+ }
+ }
+
+ IVersion[] versions = parseVersionInterval(versionInterval);
+ m_versionLow = versions[0];
+ if (versions.length == 2)
+ {
+ m_versionHigh = versions[1];
+ }
+ }
+
+ public String getId()
+ {
+ return m_id;
+ }
+
+ public IDirective[] getDirectives()
+ {
+ return m_directives;
+ }
+
+ public IAttribute[] getAttributes()
+ {
+ return m_attrs;
+ }
+
+ public IVersion getVersionLow()
+ {
+ return m_versionLow;
+ }
+
+ public IVersion getVersionHigh()
+ {
+ return m_versionHigh;
+ }
+
+ public boolean isOptional()
+ {
+ return m_isOptional;
+ }
+
+ // PREVIOUSLY PART OF COMPATIBILITY POLICY.
+ public boolean doesSatisfy(IPackage pkg)
+ {
+ // For packages to be compatible, they must have the
+ // same name.
+ if (!m_id.equals(pkg.getId()))
+ {
+ return false;
+ }
+
+ return isVersionInRange(m_versionLow, pkg.getVersionLow(), pkg.getVersionHigh())
+ && doAttributesMatch(pkg);
+ }
+
+ // PREVIOUSLY PART OF COMPATIBILITY POLICY.
+ public static boolean isVersionInRange(IVersion version, IVersion low, IVersion high)
+ {
+ // We might not have an upper end to the range.
+ if (high == null)
+ {
+ return (version.compareTo(low) >= 0);
+ }
+ else if (low.isInclusive() && high.isInclusive())
+ {
+ return (version.compareTo(low) >= 0) && (version.compareTo(high) <= 0);
+ }
+ else if (high.isInclusive())
+ {
+ return (version.compareTo(low) > 0) && (version.compareTo(high) <= 0);
+ }
+ else if (low.isInclusive())
+ {
+ return (version.compareTo(low) >= 0) && (version.compareTo(high) < 0);
+ }
+
+ return (version.compareTo(low) > 0) && (version.compareTo(high) < 0);
+ }
+
+ private boolean doAttributesMatch(IPackage pkg)
+ {
+ // Cycle through all attributes of the specified package
+ // and make sure their values match the attribute values
+ // of this package.
+ for (int attrIdx = 0; attrIdx < pkg.getAttributes().length; attrIdx++)
+ {
+ // Get current attribute from specified package.
+ IAttribute attr = pkg.getAttributes()[attrIdx];
+
+ // Ignore version attribute, since it is a special case that
+ // has already been compared using isVersionInRange() before
+ // the call to this method was made.
+ if (attr.getName().equals(Constants.VERSION_ATTRIBUTE))
+ {
+ continue;
+ }
+
+ // Check if this package has the same attribute.
+ boolean found = false;
+ for (int thisAttrIdx = 0;
+ (!found) && (thisAttrIdx < m_attrs.length);
+ thisAttrIdx++)
+ {
+ // Get current attribute for this package.
+ IAttribute thisAttr = m_attrs[thisAttrIdx];
+ // Check if the attribute names are equal.
+ if (attr.getName().equals(thisAttr.getName()))
+ {
+ // If the values are not equal, then return false immediately.
+ // We should not compare version values here, since they are
+ // a special case and have already been compared by a call to
+ // isVersionInRange() before getting here; however, it is
+ // possible for version to be mandatory, so make sure it is
+ // present below.
+ if (!attr.getValue().equals(thisAttr.getValue()))
+ {
+ return false;
+ }
+ found = true;
+ }
+ }
+ // If the attribute was not found, then return false.
+ if (!found)
+ {
+ return false;
+ }
+ }
+
+ // Now, cycle through all attributes of this package and verify that
+ // all mandatory attributes are present in the speceified package.
+ for (int thisAttrIdx = 0; thisAttrIdx < m_attrs.length; thisAttrIdx++)
+ {
+ // Get current attribute for this package.
+ IAttribute thisAttr = m_attrs[thisAttrIdx];
+
+ // If the attribute is mandatory, then make sure
+ // the specified package has the attribute.
+ if (thisAttr.isMandatory())
+ {
+ boolean found = false;
+ for (int attrIdx = 0;
+ (!found) && (attrIdx < pkg.getAttributes().length);
+ attrIdx++)
+ {
+ // Get current attribute from specified package.
+ IAttribute attr = pkg.getAttributes()[attrIdx];
+
+ // Check if the attribute names are equal
+ // and set found flag.
+ if (thisAttr.getName().equals(attr.getName()))
+ {
+ found = true;
+ }
+ }
+ // If not found, then return false.
+ if (!found)
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ public String toString()
+ {
+ String msg = getId();
+ for (int i = 0; (m_directives != null) && (i < m_directives.length); i++)
+ {
+ msg = msg + " [" + m_directives[i].getName() + ":="+ m_directives[i].getName() + "]";
+ }
+ for (int i = 0; (m_attrs != null) && (i < m_attrs.length); i++)
+ {
+ msg = msg + " [" + m_attrs[i].getValue() + "="+ m_attrs[i].getValue() + "]";
+ }
+ return msg;
+ }
+
+ // Like this: pkg1; pkg2; dir1:=dirval1; dir2:=dirval2; attr1=attrval1; attr2=attrval2,
+ // pkg1; pkg2; dir1:=dirval1; dir2:=dirval2; attr1=attrval1; attr2=attrval2
+ public static IPackage[] parseImportOrExportHeader(String s)
+ {
+ IPackage[] pkgs = null;
+ if (s != null)
+ {
+ if (s.length() == 0)
+ {
+ throw new IllegalArgumentException(
+ "The import and export headers cannot be an empty string.");
+ }
+ String[] ss = parseDelimitedString(s, ","); // FelixConstants.CLASS_PATH_SEPARATOR
+ pkgs = parsePackageStrings(ss);
+ }
+ return (pkgs == null) ? new IPackage[0] : pkgs;
+ }
+
+ // Like this: pkg1; pkg2; dir1:=dirval1; dir2:=dirval2; attr1=attrval1; attr2=attrval2
+ public static IPackage[] parsePackageStrings(String[] ss)
+ throws IllegalArgumentException
+ {
+ if (ss == null)
+ {
+ return null;
+ }
+
+ List completeList = new ArrayList();
+ for (int ssIdx = 0; ssIdx < ss.length; ssIdx++)
+ {
+ // Break string into semi-colon delimited pieces.
+ String[] pieces = parseDelimitedString(
+ ss[ssIdx], ";"); // FelixConstants.PACKAGE_SEPARATOR
+
+ // Count the number of different packages; packages
+ // will not have an '=' in their string. This assumes
+ // that packages come first, before directives and
+ // attributes.
+ int pkgCount = 0;
+ for (int pieceIdx = 0; pieceIdx < pieces.length; pieceIdx++)
+ {
+ if (pieces[pieceIdx].indexOf('=') >= 0)
+ {
+ break;
+ }
+ pkgCount++;
+ }
+
+ // Error if no packages were specified.
+ if (pkgCount == 0)
+ {
+ throw new IllegalArgumentException(
+ "No packages specified on import: " + ss[ssIdx]);
+ }
+
+ // Parse the directives/attributes.
+ IDirective[] dirs = new IDirective[pieces.length - pkgCount];
+ IAttribute[] attrs = new IAttribute[pieces.length - pkgCount];
+ int dirCount = 0, attrCount = 0;
+ int idx = -1;
+ String sep = null;
+ for (int pieceIdx = pkgCount; pieceIdx < pieces.length; pieceIdx++)
+ {
+ // Check if it is a directive.
+ if ((idx = pieces[pieceIdx].indexOf(":=")) >= 0) // FelixConstants.DIRECTIVE_SEPARATOR
+ {
+ sep = ":="; // FelixConstants.DIRECTIVE_SEPARATOR
+ }
+ // Check if it is an attribute.
+ else if ((idx = pieces[pieceIdx].indexOf("=")) >= 0) // FelixConstants.ATTRIBUTE_SEPARATOR
+ {
+ sep = "="; // FelixConstants.ATTRIBUTE_SEPARATOR
+ }
+ // It is an error.
+ else
+ {
+ throw new IllegalArgumentException(
+ "Not a directive/attribute: " + ss[ssIdx]);
+ }
+
+ String key = pieces[pieceIdx].substring(0, idx).trim();
+ String value = pieces[pieceIdx].substring(idx + sep.length()).trim();
+
+ // Remove quotes, if value is quoted.
+ if (value.startsWith("\"") && value.endsWith("\""))
+ {
+ value = value.substring(1, value.length() - 1);
+ }
+
+ // Save the directive/attribute in the appropriate array.
+ if (sep.equals(":=")) // FelixConstants.DIRECTIVE_SEPARATOR
+ {
+ dirs[dirCount++] = new R4Directive(key, value);
+ }
+ else
+ {
+ attrs[attrCount++] = new R4Attribute(key, value, false);
+ }
+ }
+
+ // Shrink directive array.
+ IDirective[] dirsFinal = new IDirective[dirCount];
+ System.arraycopy(dirs, 0, dirsFinal, 0, dirCount);
+ // Shrink attribute array.
+ IAttribute[] attrsFinal = new IAttribute[attrCount];
+ System.arraycopy(attrs, 0, attrsFinal, 0, attrCount);
+
+ // Create package attributes for each package and
+ // set directives/attributes. Add each package to
+ // completel list of packages.
+ IPackage[] pkgs = new IPackage[pkgCount];
+ for (int pkgIdx = 0; pkgIdx < pkgCount; pkgIdx++)
+ {
+ pkgs[pkgIdx] = new R4Package(pieces[pkgIdx], dirsFinal, attrsFinal);
+ completeList.add(pkgs[pkgIdx]);
+ }
+ }
+
+ IPackage[] ips = (IPackage[])
+ completeList.toArray(new IPackage[completeList.size()]);
+ return ips;
+ }
+
+ public static IVersion[] parseVersionInterval(String interval)
+ {
+ // Check if the version is an interval.
+ if (interval.indexOf(',') >= 0)
+ {
+ String s = interval.substring(1, interval.length() - 1);
+ String vlo = s.substring(0, s.indexOf(','));
+ String vhi = s.substring(s.indexOf(',') + 1, s.length());
+ return new IVersion[] {
+ new R4Version(vlo, (interval.charAt(0) == '[')),
+ new R4Version(vhi, (interval.charAt(interval.length() - 1) == ']'))
+ };
+ }
+ else
+ {
+ return new IVersion[] { new R4Version(interval, true) };
+ }
+ }
+
+ /**
+ * Parses delimited string and returns an array containing the tokens. This
+ * parser obeys quotes, so the delimiter character will be ignored if it is
+ * inside of a quote. This method assumes that the quote character is not
+ * included in the set of delimiter characters.
+ * @param value the delimited string to parse.
+ * @param delim the characters delimiting the tokens.
+ * @return an array of string tokens or null if there were no tokens.
+ **/
+ public static String[] parseDelimitedString(String value, String delim)
+ {
+ if (value == null)
+ {
+ value = "";
+ }
+
+ List list = new ArrayList();
+
+ int CHAR = 1;
+ int DELIMITER = 2;
+ int STARTQUOTE = 4;
+ int ENDQUOTE = 8;
+
+ StringBuffer sb = new StringBuffer();
+
+ int expecting = (CHAR | DELIMITER | STARTQUOTE);
+
+ for (int i = 0; i < value.length(); i++)
+ {
+ char c = value.charAt(i);
+
+ boolean isDelimiter = (delim.indexOf(c) >= 0);
+ boolean isQuote = (c == '"');
+
+ if (isDelimiter && ((expecting & DELIMITER) > 0))
+ {
+ list.add(sb.toString().trim());
+ sb.delete(0, sb.length());
+ expecting = (CHAR | DELIMITER | STARTQUOTE);
+ }
+ else if (isQuote && ((expecting & STARTQUOTE) > 0))
+ {
+ sb.append(c);
+ expecting = CHAR | ENDQUOTE;
+ }
+ else if (isQuote && ((expecting & ENDQUOTE) > 0))
+ {
+ sb.append(c);
+ expecting = (CHAR | STARTQUOTE | DELIMITER);
+ }
+ else if ((expecting & CHAR) > 0)
+ {
+ sb.append(c);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Invalid delimited string: " + value);
+ }
+ }
+
+ if (sb.length() > 0)
+ {
+ list.add(sb.toString().trim());
+ }
+
+ return (String[]) list.toArray(new String[list.size()]);
+ }
+}
\ No newline at end of file
Added: incubator/oscar/trunk/src/org/apache/osgi/bundle/bundlerepository/R4Version.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/bundle/bundlerepository/R4Version.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/bundle/bundlerepository/R4Version.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/bundle/bundlerepository/R4Version.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.osgi.bundle.bundlerepository;
+
+import java.util.StringTokenizer;
+
+import org.apache.osgi.service.bundlerepository.IVersion;
+
+public class R4Version implements Comparable, IVersion
+{
+ private int m_major = 0;
+ private int m_minor = 0;
+ private int m_micro = 0;
+ private String m_qualifier = "";
+ private boolean m_isInclusive = true;
+
+ private static final String SEPARATOR = ".";
+
+ public R4Version(String versionString)
+ {
+ this(versionString, true);
+ }
+
+ public R4Version(String versionString, boolean isInclusive)
+ {
+ if (versionString == null)
+ {
+ versionString = "0.0.0";
+ }
+ Object[] objs = parseVersion(versionString);
+ m_major = ((Integer) objs[0]).intValue();
+ m_minor = ((Integer) objs[1]).intValue();
+ m_micro = ((Integer) objs[2]).intValue();
+ m_qualifier = (String) objs[3];
+ m_isInclusive = isInclusive;
+ }
+
+ private static Object[] parseVersion(String versionString)
+ {
+ String s = versionString.trim();
+ Object[] objs = new Object[4];
+ objs[0] = objs[1] = objs[2] = new Integer(0);
+ objs[3] = "";
+ StringTokenizer tok = new StringTokenizer(s, SEPARATOR);
+ try
+ {
+ objs[0] = Integer.valueOf(tok.nextToken());
+ if (tok.hasMoreTokens())
+ {
+ objs[1] = Integer.valueOf(tok.nextToken());
+ if (tok.hasMoreTokens())
+ {
+ objs[2] = Integer.valueOf(tok.nextToken());
+ if (tok.hasMoreTokens())
+ {
+ objs[3] = tok.nextToken();
+ }
+ }
+ }
+ }
+ catch (NumberFormatException ex)
+ {
+ throw new IllegalArgumentException("Invalid version: " + versionString);
+ }
+
+ if ((((Integer) objs[0]).intValue() < 0) ||
+ (((Integer) objs[0]).intValue() < 0) ||
+ (((Integer) objs[0]).intValue() < 0))
+ {
+ throw new IllegalArgumentException("Invalid version: " + versionString);
+ }
+
+ return objs;
+ }
+
+ /* (non-Javadoc)
+ * @see org.ungoverned.osgi.service.bundlerepository.Version#equals(java.lang.Object)
+ **/
+ public boolean equals(Object object)
+ {
+ if (!(object instanceof R4Version))
+ {
+ return false;
+ }
+ IVersion v = (IVersion) object;
+ return
+ (v.getMajorComponent() == m_major) &&
+ (v.getMinorComponent() == m_minor) &&
+ (v.getMicroComponent() == m_micro) &&
+ (v.getQualifierComponent().equals(m_qualifier));
+ }
+
+ /* (non-Javadoc)
+ * @see org.ungoverned.osgi.service.bundlerepository.Version#getMajorComponent()
+ **/
+ public int getMajorComponent()
+ {
+ return m_major;
+ }
+
+ /* (non-Javadoc)
+ * @see org.ungoverned.osgi.service.bundlerepository.Version#getMinorComponent()
+ **/
+ public int getMinorComponent()
+ {
+ return m_minor;
+ }
+
+ /* (non-Javadoc)
+ * @see org.ungoverned.osgi.service.bundlerepository.Version#getMicroComponent()
+ **/
+ public int getMicroComponent()
+ {
+ return m_micro;
+ }
+
+ /* (non-Javadoc)
+ * @see org.ungoverned.osgi.service.bundlerepository.Version#getQualifierComponent()
+ **/
+ public String getQualifierComponent()
+ {
+ return m_qualifier;
+ }
+
+ /* (non-Javadoc)
+ * @see org.ungoverned.osgi.service.bundlerepository.Version#isInclusive()
+ **/
+ public boolean isInclusive()
+ {
+ return m_isInclusive;
+ }
+
+ /* (non-Javadoc)
+ * @see org.ungoverned.osgi.service.bundlerepository.Version#compareTo(java.lang.Object)
+ **/
+ public int compareTo(Object o)
+ {
+ if (!(o instanceof R4Version))
+ throw new ClassCastException();
+
+ if (equals(o))
+ return 0;
+
+ if (isGreaterThan((IVersion) o))
+ return 1;
+
+ return -1;
+ }
+
+ private boolean isGreaterThan(IVersion v)
+ {
+ if (v == null)
+ {
+ return false;
+ }
+
+ if (m_major > v.getMajorComponent())
+ {
+ return true;
+ }
+ if (m_major < v.getMajorComponent())
+ {
+ return false;
+ }
+ if (m_minor > v.getMinorComponent())
+ {
+ return true;
+ }
+ if (m_minor < v.getMinorComponent())
+ {
+ return false;
+ }
+ if (m_micro > v.getMicroComponent())
+ {
+ return true;
+ }
+ if (m_micro < v.getMicroComponent())
+ {
+ return false;
+ }
+ if (m_qualifier.compareTo(v.getQualifierComponent()) > 0)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.ungoverned.osgi.service.bundlerepository.Version#toString()
+ **/
+ public String toString()
+ {
+ if (m_qualifier.length() == 0)
+ {
+ return m_major + "." + m_minor + "." + m_micro;
+ }
+ return m_major + "." + m_minor + "." + m_micro + "." + m_qualifier;
+ }
+}
\ No newline at end of file