blob: afb04e08d6829e0b6fee9bf0f90d206d895b8bf7 [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.karaf.shell.osgi;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.felix.service.command.CommandSession;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
public class BundleSelector {
private final CommandSession session;
private final BundleContext bundleContext;
public BundleSelector(BundleContext bundleContext, CommandSession session) {
this.bundleContext = bundleContext;
this.session = session;
}
public List<Bundle> selectBundles(List<String> ids, boolean force) throws Exception {
List<Bundle> bundles = new ArrayList<Bundle>();
if (ids != null && !ids.isEmpty()) {
for (String id : ids) {
// id is a number
Pattern pattern = Pattern.compile("^\\d+$");
Matcher matcher = pattern.matcher(id);
if (matcher.find()) {
Bundle bundle = this.getBundleById(id);
addBundle(bundle, id, force, bundles);
continue;
}
// id as a number range
pattern = Pattern.compile("^(\\d+)-(\\d+)$");
matcher = pattern.matcher(id);
if (matcher.find()) {
int index = id.indexOf('-');
long startId = Long.parseLong(id.substring(0, index));
long endId = Long.parseLong(id.substring(index + 1));
if (startId < endId) {
for (long i = startId; i <= endId; i++) {
Bundle bundle = bundleContext.getBundle(i);
addBundle(bundle, String.valueOf(i), force, bundles);
}
}
continue;
}
int index = id.indexOf('/');
List<Bundle> bundlesByName = null;
if (index != -1) {
// user has provided name and version
bundlesByName = getBundleByNameAndVersion(id.substring(0, index), id.substring(index + 1));
} else {
// user has provided only the name
bundlesByName = getBundleByName(id);
}
for (Bundle bundleByName : bundlesByName) {
addBundle(bundleByName, id, force, bundles);
}
}
}
return bundles;
}
private void addBundle(Bundle bundle, String id, boolean force, List<Bundle> bundles) throws Exception {
if (bundle == null) {
// if the bundle is null here, it's because we didn't find it
System.err.println("Bundle " + id + " is invalid");
} else {
if (force || !Util.isASystemBundle(bundleContext, bundle) || Util.accessToSystemBundleIsAllowed(bundle.getBundleId(), session)) {
bundles.add(bundle);
}
}
}
/**
* Get a bundle identified by an id number.
*
* @param id the id number.
* @return the bundle or null if not found.
*/
private Bundle getBundleById(String id) {
Bundle bundle = null;
try {
long idNumber = Long.parseLong(id);
bundle = bundleContext.getBundle(idNumber);
} catch (NumberFormatException nfe) {
// ignore
}
return bundle;
}
/**
* Get a bundles list with the name or symbolic name matching the pattern.
*
* @param name the bundle name or symbolic name pattern to match.
* @return the bundles list.
*/
private List<Bundle> getBundleByName(String name) {
return getBundleByNameAndVersion(name, null);
}
/**
* Get a bundles list with the name or symbolic name matching the name pattern and version matching the version pattern.
*
* @param name the bundle name or symbolic name regex to match.
* @param version the bundle version regex to match.
* @return the bundles list.
*/
private List<Bundle> getBundleByNameAndVersion(String name, String version) {
Bundle[] bundles = bundleContext.getBundles();
ArrayList<Bundle> result = new ArrayList<Bundle>();
Pattern namePattern = Pattern.compile(name);
for (int i = 0; i < bundles.length; i++) {
String bundleSymbolicName = bundles[i].getSymbolicName();
// skip bundles without Bundle-SymbolicName header
if (bundleSymbolicName == null) {
continue;
}
Matcher symbolicNameMatcher = namePattern.matcher(bundleSymbolicName);
Matcher nameMatcher = null;
String bundleName = (String) bundles[i].getHeaders().get(Constants.BUNDLE_NAME);
if (bundleName != null) {
nameMatcher = namePattern.matcher(bundleName);
}
if (version != null) {
String bundleVersion = (String) bundles[i].getHeaders().get(Constants.BUNDLE_VERSION);
if (bundleVersion != null) {
boolean nameMatch = (nameMatcher != null && nameMatcher.find()) || symbolicNameMatcher.find();
if (nameMatch) {
Pattern versionPattern = Pattern.compile(version);
Matcher versionMatcher = versionPattern.matcher(bundleVersion);
if (versionMatcher.find()) {
result.add(bundles[i]);
}
}
}
} else {
boolean nameMatch = (nameMatcher != null && nameMatcher.find()) || symbolicNameMatcher.find();
if (nameMatch) {
result.add(bundles[i]);
}
}
}
return result;
}
}