/****************************************************************************
* Copyright (C) 2013 HS Coburg.
* All rights reserved.
* Contact: ecsec GmbH (info@ecsec.de)
*
* This file is part of the Open eCard App.
*
* GNU General Public License Usage
* This file may be used under the terms of the GNU General Public
* License version 3.0 as published by the Free Software Foundation
* and appearing in the file LICENSE.GPL included in the packaging of
* this file. Please review the following information to ensure the
* GNU General Public License version 3.0 requirements will be met:
* http://www.gnu.org/copyleft/gpl.html.
*
* Other Usage
* Alternatively, this file may be used in accordance with the terms
* and conditions contained in a signed written agreement between
* you and ecsec GmbH.
*
***************************************************************************/
package org.openecard.addon;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.commons.jci.monitor.FilesystemAlterationMonitor;
import org.openecard.addon.manifest.AddonSpecification;
import org.openecard.addon.manifest.AppExtensionSpecification;
import org.openecard.addon.manifest.AppPluginSpecification;
import org.openecard.addon.manifest.LocalizedString;
import org.openecard.addon.manifest.ProtocolPluginSpecification;
import org.openecard.common.util.FileUtils;
import org.openecard.ws.marshal.WSMarshallerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This registry provides access to all addons in the plugins directory.
* Adding and removing addon-files at runtime is supported.
*
* @author Dirk Petrautzki <petrautzki@hs-coburg.de>
*/
public class FileRegistry implements AddonRegistry {
private static final Logger logger = LoggerFactory.getLogger(FileRegistry.class.getName());
private static final ArrayList<AddonSpecification> registeredAddons = new ArrayList<AddonSpecification>();
private static final HashMap<String, File> files = new HashMap<String, File>();
public FileRegistry() throws WSMarshallerException {
String addonPath;
try {
addonPath = FileUtils.getHomeConfigDir() + File.separator + "addons" + File.separator;
} catch (SecurityException e) {
logger.error("Failed to get add-on directory; FileRegistry won't work.", e);
return;
} catch (IOException e) {
logger.error("Failed to get add-on directory; FileRegistry won't work.", e);
return;
}
startFileMonitor(addonPath);
}
private void startFileMonitor(String addonPath) throws WSMarshallerException {
File f = new File(addonPath);
logger.debug("Starting file alteration monitor on path: {}", f.getPath());
FilesystemAlterationMonitor fam = new FilesystemAlterationMonitor();
fam.addListener(f, new PluginDirectoryAlterationListener(this));
fam.start();
}
public void register(AddonSpecification desc, File file) {
registeredAddons.add(desc);
files.put(desc.getId(), file);
}
public void unregister(File file) {
Set<Entry<String, File>> entrySet = files.entrySet();
Iterator<Entry<String, File>> iterator = entrySet.iterator();
while (iterator.hasNext()) {
Entry<String, File> next = iterator.next();
if (next.getValue().equals(file)) {
String id = next.getKey();
AddonSpecification desc = this.search(id);
registeredAddons.remove(desc);
files.remove(id);
logger.debug("Successfully removed addon {}", file.getName());
break;
}
}
}
@Override
public Set<AddonSpecification> listAddons() {
Set<AddonSpecification> list = new HashSet<AddonSpecification>();
list.addAll(registeredAddons);
return list;
}
@Override
public AddonSpecification search(String id) {
for (AddonSpecification desc : registeredAddons) {
if (desc.getId().equals(id)) {
return desc;
}
}
return null;
}
@Override
public Set<AddonSpecification> searchByName(String name) {
Set<AddonSpecification> matchingAddons = new HashSet<AddonSpecification>();
for (AddonSpecification desc : registeredAddons) {
for (LocalizedString s : desc.getLocalizedName()) {
if (s.getValue().equals(name)) {
matchingAddons.add(desc);
}
}
}
return matchingAddons;
}
@Override
public Set<AddonSpecification> searchIFDProtocol(String uri) {
Set<AddonSpecification> matchingAddons = new HashSet<AddonSpecification>();
for (AddonSpecification desc : registeredAddons) {
ProtocolPluginSpecification protocolDesc = desc.searchIFDActionByURI(uri);
if (protocolDesc != null) {
matchingAddons.add(desc);
}
}
return matchingAddons;
}
@Override
public Set<AddonSpecification> searchSALProtocol(String uri) {
Set<AddonSpecification> matchingAddons = new HashSet<AddonSpecification>();
for (AddonSpecification desc : registeredAddons) {
ProtocolPluginSpecification protocolDesc = desc.searchSALActionByURI(uri);
if (protocolDesc != null) {
matchingAddons.add(desc);
}
}
return matchingAddons;
}
@Override
public ClassLoader downloadAddon(AddonSpecification addonSpec) {
String aId = addonSpec.getId();
// TODO use other own classloader impl with security features
URL[] url = new URL[1];
try {
url[0] = files.get(aId).toURI().toURL();
} catch (MalformedURLException e) {
// TODO will this ever happen?
logger.error(e.getMessage(), e);
}
URLClassLoader ucl = new URLClassLoader(url);
return ucl;
}
@Override
public Set<AddonSpecification> searchByResourceName(String resourceName) {
Set<AddonSpecification> matchingAddons = new HashSet<AddonSpecification>();
for (AddonSpecification desc : registeredAddons) {
AppPluginSpecification actionDesc = desc.searchByResourceName(resourceName);
if (actionDesc != null) {
matchingAddons.add(desc);
}
}
return matchingAddons;
}
@Override
public Set<AddonSpecification> searchByActionId(String actionId) {
Set<AddonSpecification> matchingAddons = new HashSet<AddonSpecification>();
for (AddonSpecification desc : registeredAddons) {
AppExtensionSpecification actionDesc = desc.searchByActionId(actionId);
if (actionDesc != null) {
matchingAddons.add(desc);
}
}
return matchingAddons;
}
}