001/* 002 * Bnd Nexus Search Plugin 003 * Copyright (C) 2017 Michael N. Lipp 004 * 005 * This program is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU Affero General Public License as published by 007 * the Free Software Foundation; either version 3 of the License, or 008 * (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, but 011 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 012 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 013 * for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License along 016 * with this program; if not, see <http://www.gnu.org/licenses/>. 017 */ 018 019package de.mnl.osgi.bnd.repository.maven.provider; 020 021import aQute.bnd.build.Workspace; 022import aQute.bnd.http.HttpClient; 023import aQute.bnd.osgi.repository.BaseRepository; 024import aQute.bnd.osgi.repository.BridgeRepository; 025import aQute.bnd.osgi.repository.BridgeRepository.ResourceInfo; 026import aQute.bnd.service.Plugin; 027import aQute.bnd.service.Refreshable; 028import aQute.bnd.service.Registry; 029import aQute.bnd.service.RegistryPlugin; 030import aQute.bnd.service.RepositoryListenerPlugin; 031import aQute.bnd.service.RepositoryPlugin; 032import aQute.bnd.util.repository.DownloadListenerPromise; 033import aQute.bnd.version.Version; 034import aQute.lib.converter.Converter; 035import aQute.lib.io.IO; 036import aQute.maven.api.Archive; 037import aQute.service.reporter.Reporter; 038import de.mnl.osgi.bnd.repository.maven.nexussearch.NexusSearchConfiguration; 039import de.mnl.osgi.bnd.repository.maven.nexussearch.NexusSearchOsgiRepository; 040import java.io.File; 041import java.io.InputStream; 042import java.net.MalformedURLException; 043import java.net.URL; 044import java.util.Collection; 045import java.util.List; 046import java.util.Map; 047import java.util.SortedSet; 048import org.osgi.resource.Capability; 049import org.osgi.resource.Requirement; 050import org.osgi.service.repository.Repository; 051import org.osgi.util.promise.Promise; 052 053/** 054 * Provide a {@link NexusSearchOsgiRepository} as a bnd repository. The interesting 055 * work is done by the {@link NexusSearchOsgiRepository}. 056 */ 057public class NexusSearchRepositoryProvider extends BaseRepository 058 implements Repository, Plugin, RegistryPlugin, RepositoryPlugin, 059 Refreshable { 060// private final static Logger logger = LoggerFactory.getLogger( 061// NexusSearchRepositoryProvider.class); 062 private static final String MAVEN_REPO_LOCAL 063 = System.getProperty("maven.repo.local", "~/.m2/repository"); 064 065 private boolean initialized = false; 066 private File localRepo; 067 private NexusSearchConfiguration configuration; 068 private String name = "OssSonatype"; 069 private Registry registry = null; 070 private Reporter reporter; 071 private NexusSearchOsgiRepository osgiRepository = null; 072 private URL server = null; 073 private BridgeRepository bridge; 074 075 @Override 076 public void setProperties(Map<String, String> properties) throws Exception { 077 configuration 078 = Converter.cnv(NexusSearchConfiguration.class, properties); 079 name = configuration.name("OssSonatype"); 080 server = new URL(configuration.server() != null 081 ? configuration.server() 082 : "https://oss.sonatype.org"); 083 } 084 085 @Override 086 public void setRegistry(Registry registry) { 087 this.registry = registry; 088 } 089 090 @Override 091 public void setReporter(Reporter reporter) { 092 this.reporter = reporter; 093 } 094 095 @Override 096 public String getName() { 097 return name; 098 } 099 100 @Override 101 public PutResult put(InputStream stream, PutOptions options) 102 throws Exception { 103 throw new IllegalStateException("Read-only repository"); 104 } 105 106 @Override 107 public boolean canWrite() { 108 return false; 109 } 110 111 /** 112 * Performs initialization. Initialization must be delayed because the 113 * precise sequence of injecting dependencies seems to be undefined. 114 * @throws MalformedURLException 115 */ 116 private synchronized void init() { 117 if (initialized) { 118 return; 119 } 120 initialized = true; 121 String queryString = configuration.query(); 122 Workspace workspace = registry.getPlugin(Workspace.class); 123 HttpClient client = registry.getPlugin(HttpClient.class); 124 File obrIndexFile = workspace.getFile(getLocation()); 125 File mvnReposFile = workspace.getFile( 126 "cnf/cache/nexus-search-" + name + "-repositories.xml"); 127 localRepo = IO.getFile(configuration.local(MAVEN_REPO_LOCAL)); 128 try { 129 osgiRepository = new NexusSearchOsgiRepository( 130 name, server, localRepo, obrIndexFile, mvnReposFile, 131 queryString, configuration.searchBreadth(3), 132 configuration.chunkSize(500), reporter, client); 133 bridge = new BridgeRepository(osgiRepository); 134 } catch (Exception e) { 135 throw new RuntimeException(e); 136 } 137 } 138 139 @Override 140 public File getRoot() throws Exception { 141 return localRepo; 142 } 143 144 @Override 145 public boolean refresh() throws Exception { 146 init(); 147 if (!osgiRepository.refresh()) { 148 return false; 149 } 150 bridge = new BridgeRepository(osgiRepository); 151 for (RepositoryListenerPlugin listener : registry 152 .getPlugins(RepositoryListenerPlugin.class)) { 153 try { 154 listener.repositoryRefreshed(this); 155 } catch (Exception e) { 156 reporter.exception(e, "Updating listener plugin %s", listener); 157 } 158 } 159 return true; 160 } 161 162 @Override 163 public File get(String bsn, Version version, Map<String, String> properties, 164 DownloadListener... listeners) throws Exception { 165 init(); 166 ResourceInfo resource = bridge.getInfo(bsn, version); 167 if (resource == null) { 168 return null; 169 } 170 171 String name = resource.getInfo().name(); 172 Archive archive = Archive.valueOf(name); 173 174 Promise<File> p = osgiRepository.mavenRepository().get(archive); 175 176 if (listeners.length == 0) { 177 return p.getValue(); 178 } 179 180 new DownloadListenerPromise(reporter, 181 name + ": get " + bsn + ";" + version, p, listeners); 182 return osgiRepository.mavenRepository().toLocalFile(archive); 183 } 184 185 @Override 186 public List<String> list(String pattern) throws Exception { 187 init(); 188 return bridge.list(pattern); 189 } 190 191 @Override 192 public SortedSet<Version> versions(String bsn) throws Exception { 193 init(); 194 return bridge.versions(bsn); 195 } 196 197 @Override 198 public String getLocation() { 199 return "cnf/cache/nexus-search-" + name + ".xml"; 200 } 201 202 @Override 203 public Map<Requirement, Collection<Capability>> findProviders( 204 Collection<? extends Requirement> requirements) { 205 init(); 206 return osgiRepository.findProviders(requirements); 207 } 208}