| /* |
| * 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 (Resource resource : resources) { |
| System.out.println(" " + getResourceId(resource) |
| + " (" + resource.getVersion() + ")"); |
| } |
| } |
| if (deployOptional) { |
| resources = resolver.getOptionalResources(); |
| if ((resources != null) && (resources.length > 0)) { |
| System.out.println("\nOptional resource(s):"); |
| printUnderline(System.out, 21); |
| for (Resource resource : resources) { |
| System.out.println(" " + getResourceId(resource) + " (" + resource.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 (Reason req : reqs) { |
| System.out.println(" " + req.getRequirement().getFilter()); |
| System.out.println(" " + getResourceId(req.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"); |
| |
| boolean modified = false; |
| try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(sysTmp)))) { |
| if (sys.exists()) { |
| try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(sys)))) { |
| 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(); |
| } |
| } |
| } |
| 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(); |
| } |
| } |
| |
| sys.delete(); |
| sysTmp.renameTo(sys); |
| |
| } catch (Exception e) { |
| System.err.println("Error while persisting repository list"); |
| } |
| } |
| |
| } |