blob: 60dba4b6c879b4793b07d74dc20f6aa518425115 [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.cave.server.storage;
import org.apache.karaf.cave.server.api.CaveRepository;
import org.apache.karaf.cave.server.api.CaveRepositoryService;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.repository.Repository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Properties;
/**
* Default implementation of the CaveRepositoryService.
*/
public class CaveRepositoryServiceImpl implements CaveRepositoryService {
private static final Logger LOGGER = LoggerFactory.getLogger(CaveRepositoryServiceImpl.class);
public static final String STORAGE_FILE = "repositories.properties";
private BundleContext bundleContext;
private File storageLocation;
private final Map<String, CaveRepositoryImpl> repositories = new HashMap<>();
private final Map<String, ServiceRegistration<Repository>> services = new HashMap<>();
public File getStorageLocation() {
return this.storageLocation;
}
public void setStorageLocation(File storageLocation) {
this.storageLocation = storageLocation;
}
public BundleContext getBundleContext() {
return bundleContext;
}
public void setBundleContext(BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
/**
* Create a Cave repository.
*
* @param name the name of the repository
* @param scan if true, the repository is scanned at creation time.
* @return the Cave repository.
* @throws Exception in case of creation failure.
*/
public synchronized CaveRepository create(String name, boolean scan) throws Exception {
File location = new File(storageLocation, name);
return create(name, location.getAbsolutePath(), scan);
}
/**
* Create a Cave repository.
*
* @param name the name of the repository.
* @param location the storage location of the repository.
* @param scan if true, the repository is scanned at creation time.
* @return the Cave repository.
* @throws Exception in case of creation failure.
*/
public synchronized CaveRepository create(String name, String location, boolean scan) throws Exception {
if (repositories.get(name) != null) {
throw new IllegalArgumentException("Cave repository " + name + " already exists");
}
CaveRepositoryImpl repository = new CaveRepositoryImpl(name, location, scan);
repositories.put(name, repository);
save();
return repository;
}
/**
* Remove the OSGi Repository service corresponding to Cave repository.
*
* @param name the name of Cave repository to remove.
* @throws Exception in case of remove failure.
*/
public synchronized void uninstall(String name) throws Exception {
CaveRepository repository = getRepository(name);
if (repository == null) {
throw new IllegalArgumentException("Cave repository " + name + " doesn't exist");
}
ServiceRegistration<Repository> registration = services.remove(name);
if (registration != null) {
registration.unregister();
}
save();
}
/**
* Remove a Cave repository from the repositories registry.
* @param name the name of the repository.
* @throws Exception
*/
public synchronized void remove(String name) throws Exception {
CaveRepository repository = getRepository(name);
if (repository == null) {
throw new IllegalArgumentException("Cave repository " + name + " doesn't exist");
}
repositories.remove(name);
save();
}
/**
* Destroy a Cave repository. It removes the repository from the repositories registry
* and cleanup the repository storage.
*
* @param name the name of the repository.
* @throws Exception
*/
public synchronized void destroy(String name) throws Exception {
CaveRepository repository = getRepository(name);
if (repository == null) {
throw new IllegalArgumentException("Cave repository " + name + " doesn't exist");
}
repositories.remove(name);
repository.cleanup();
save();
}
/**
* Expose a Cave repository as a OSGi Repository service.
* NB: this method allows refresh the repository in the repository "client".
*
* @param name the name of the Cave repository.
* @throws Exception in case of registration failure.
*/
public synchronized void install(String name) throws Exception {
CaveRepositoryImpl caveRepository = getRepository(name);
if (caveRepository == null) {
throw new IllegalArgumentException("Cave repository " + name + " doesn't exist");
}
ServiceRegistration<Repository> registration = services.get(name);
if (registration == null) {
Hashtable<String, String> props = new Hashtable<>();
props.put(Constants.SERVICE_DESCRIPTION, name);
props.put(Repository.URL, caveRepository.getLocation());
registration = bundleContext.registerService(Repository.class, caveRepository.getRepository(), props);
services.put(name, registration);
}
save();
}
/**
* Get the list of all Cave repositories.
*
* @return the list of all Cave repositories.
*/
public synchronized CaveRepository[] getRepositories() {
return repositories.values().toArray(new CaveRepository[repositories.size()]);
}
/**
* Get the Cave repository identified by name.
*
* @param name the name of the Cave repository to look for.
* @return the corresponding Cave repository.
*/
public synchronized CaveRepositoryImpl getRepository(String name) {
return repositories.get(name);
}
/**
* Store the repositories into the properties file
*/
synchronized void save() throws Exception {
Properties storage = new Properties();
CaveRepository[] repositories = this.getRepositories();
storage.setProperty("count", Integer.toString(repositories.length));
for (int i = 0; i < repositories.length; i++) {
storage.setProperty("item." + i + ".name", repositories[i].getName());
storage.setProperty("item." + i + ".location", repositories[i].getLocation());
storage.setProperty("item." + i + ".installed", Boolean.toString(services.containsKey(repositories[i].getName())));
}
saveStorage(storage, new File(storageLocation, STORAGE_FILE), "Cave Service storage");
}
/**
* Write the Cave repositories storage properties into a file.
*
* @param properties the Cave repositories storage properties.
* @param location the output file location.
* @param comment a comment to write in the properties file.
* @throws IOException in case of saving failure.
*/
private void saveStorage(Properties properties, File location, String comment) throws IOException {
OutputStream os = null;
try {
if (!location.exists()) {
location.getParentFile().mkdirs();
location.createNewFile();
}
os = new FileOutputStream(location);
properties.store(os, comment);
} finally {
if (os != null) {
os.close();
}
}
}
/**
* Load a storage property from a given file.
*
* @param location the properties file to load.
* @return the loaded Properties.
* @throws IOException in case of loading failure.
*/
private Properties loadStorage(File location) throws IOException {
InputStream is = null;
try {
is = new FileInputStream(location);
Properties props = new Properties();
props.load(is);
return props;
} finally {
if (is != null) {
is.close();
}
}
}
/**
* Load the Cave repositories set from the storage properties file.
*/
public synchronized void init() throws Exception {
try {
File storageFile = new File(storageLocation, STORAGE_FILE);
Properties storage = loadStorage(storageFile);
int count = 0;
if (storage.getProperty("count") != null) {
count = Integer.parseInt(storage.getProperty("count"));
}
for (int i = 0; i < count; i++) {
String name = storage.getProperty("item." + i + ".name");
String location = storage.getProperty("item." + i + ".location");
boolean installed = Boolean.parseBoolean(storage.getProperty("item." + i + ".installed"));
if (name != null) {
CaveRepositoryImpl repository = new CaveRepositoryImpl(name, location, false);
repositories.put(name, repository);
if (installed) {
install(name);
}
}
}
} catch (Exception e) {
LOGGER.debug("Unable to load Cave repositories");
LOGGER.trace("Unable to load Cave repositories", e);
}
}
}