/* * 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.obr.command; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintStream; import java.util.List; import org.apache.felix.bundlerepository.Reason; import org.apache.felix.bundlerepository.Repository; import org.apache.felix.bundlerepository.RepositoryAdmin; import org.apache.felix.bundlerepository.Requirement; import org.apache.felix.bundlerepository.Resolver; import org.apache.felix.bundlerepository.Resource; import org.apache.karaf.shell.api.action.Action; import org.apache.karaf.shell.api.action.lifecycle.Reference; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.Version; public abstract class ObrCommandSupport implements Action { protected static final char VERSION_DELIM = ','; @Reference private RepositoryAdmin repositoryAdmin; @Reference BundleContext bundleContext; public void setRepositoryAdmin(RepositoryAdmin repositoryAdmin) { this.repositoryAdmin = repositoryAdmin; } @Override public Object execute() throws Exception { doExecute(repositoryAdmin); return null; } abstract void doExecute(RepositoryAdmin admin) throws Exception; protected Resource[] searchRepository(RepositoryAdmin admin, String targetId, String targetVersion) throws InvalidSyntaxException { // Try to see if the targetId is a bundle ID. try { Bundle bundle = bundleContext.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 admin.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]; } protected String[] getTarget(String bundle) { String[] target; int idx = bundle.indexOf(VERSION_DELIM); if (idx > 0) { target = new String[]{bundle.substring(0, idx), bundle.substring(idx + 1)}; } else { target = new String[]{bundle, null}; } return target; } protected void printUnderline(PrintStream out, int length) { for (int i = 0; i < length; i++) { out.print('-'); } out.println(""); } protected void doDeploy(RepositoryAdmin admin, List<String> bundles, boolean start, boolean deployOptional) throws Exception { Resolver resolver = admin.resolver(); for (String bundle : bundles) { String[] target = getTarget(bundle); Resource resource = selectNewestVersion(searchRepository(admin, target[0], target[1])); if (resource != null) { resolver.add(resource); } else { System.err.println("Unknown bundle - " + target[0]); } } if ((resolver.getAddedResources() != null) && (resolver.getAddedResources().length > 0)) { if (resolver.resolve(deployOptional ? 0 : Resolver.NO_OPTIONAL_RESOURCES)) { System.out.println("Target resource(s):"); printUnderline(System.out, 19); Resource[] resources = resolver.getAddedResources(); for (int resIdx = 0; (resources != null) && (resIdx < resources.length); resIdx++) { System.out.println(" " + getResourceId(resources[resIdx]) + " (" + resources[resIdx].getVersion() + ")"); } resources = resolver.getRequiredResources(); if ((resources != null) && (resources.length > 0)) { System.out.println("\nRequired resource(s):"); printUnderline(System.out, 21); for (int resIdx = 0; resIdx < resources.length; resIdx++) { System.out.println(" " + getResourceId(resources[resIdx]) + " (" + resources[resIdx].getVersion() + ")"); } } if (deployOptional) { resources = resolver.getOptionalResources(); if ((resources != null) && (resources.length > 0)) { System.out.println("\nOptional resource(s):"); printUnderline(System.out, 21); for (int resIdx = 0; resIdx < resources.length; resIdx++) { System.out.println(" " + getResourceId(resources[resIdx]) + " (" + resources[resIdx].getVersion() + ")"); } } } try { System.out.print("\nDeploying..."); resolver.deploy(start ? Resolver.START : 0); System.out.println("done."); } catch (IllegalStateException ex) { System.err.println(ex); } } else { Reason[] reqs = resolver.getUnsatisfiedRequirements(); if ((reqs != null) && (reqs.length > 0)) { System.out.println("Unsatisfied requirement(s):"); printUnderline(System.out, 27); for (int reqIdx = 0; reqIdx < reqs.length; reqIdx++) { System.out.println(" " + reqs[reqIdx].getRequirement().getFilter()); System.out.println(" " + getResourceId(reqs[reqIdx].getResource())); } } else { System.out.println("Could not resolve targets."); } } } } protected String getResourceId(Resource resource) { return resource.getPresentationName() != null ? resource.getPresentationName() : resource.getSymbolicName(); } protected Requirement parseRequirement(RepositoryAdmin admin, String req) throws InvalidSyntaxException { int p = req.indexOf(':'); String name; String filter; if (p > 0) { name = req.substring(0, p); filter = req.substring(p + 1); } else { if (req.contains("package")) { name = "package"; } else if (req.contains("service")) { name = "service"; } else if (req.contains("osgi.extender")) { name = "osgi.extender"; } else { name = "bundle"; } filter = req; } if (!filter.startsWith("(")) { filter = "(" + filter + ")"; } return admin.getHelper().requirement(name, filter); } protected Requirement[] parseRequirements(RepositoryAdmin admin, List<String> requirements) throws InvalidSyntaxException { Requirement[] reqs = new Requirement[requirements.size()]; for (int i = 0; i < reqs.length; i++) { reqs[i] = parseRequirement(admin, requirements.get(i)); } return reqs; } public static final String REPOSITORY_URL_PROP = "obr.repository.url"; protected void persistRepositoryList(RepositoryAdmin admin) { try { StringBuilder sb = new StringBuilder(); for (Repository repo : admin.listRepositories()) { if (sb.length() > 0) { sb.append(" "); } sb.append(repo.getURI()); } File etc = new File(System.getProperty("karaf.etc")); File sys = new File(etc, "config.properties"); File sysTmp = new File(etc, "config.properties.tmp"); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(sysTmp))); boolean modified = false; try { if (sys.exists()) { BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(sys))); try { String line = reader.readLine(); while (line != null) { if (line.matches("obr\\.repository\\.url[:= ].*")) { modified = true; line = "obr.repository.url = " + sb.toString(); } writer.write(line); writer.newLine(); line = reader.readLine(); } } finally { reader.close(); } } if (!modified) { writer.newLine(); writer.write("# "); writer.newLine(); writer.write("# OBR Repository list"); writer.newLine(); writer.write("# "); writer.newLine(); writer.write("obr.repository.url = " + sb.toString()); writer.newLine(); writer.newLine(); } } finally { writer.close(); } sys.delete(); sysTmp.renameTo(sys); } catch (Exception e) { System.err.println("Error while persisting repository list"); } } }