All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.intarsys.tools.provider.Providers Maven / Gradle / Ivy

There is a newer version: 4.11
Show newest version
/*
 * @(#)ServiceLoader.java	1.10 06/04/10
 *
 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

package de.intarsys.tools.provider;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.ServiceLoader;
import java.util.logging.Level;
import java.util.logging.Logger;

import de.intarsys.tools.stream.StreamTools;

/**
 * This is an alternative service- or provider loading tool.
 * 

* The standard {@link ServiceLoader} architecture is quite unfriendly to * reflective access and is even more unfriendly to a lightweight generic * build&deployment procedure. *

* This implementation uses a single file "META-INF/provider/provider.list" to * enumerate service/implementation pairs. Each service is listed on a line of * its own. The service is followed by a ";", then followed by the * implementation class. Empty lines are ignored. */ public class Providers { static class ProviderEntry { public String serviceName; public String providerName; public Object provider; } public static final char COMMENT = '#'; public static final String SEPARATOR = ";"; private static final Map providers = new HashMap(); private static final String PROVIDERLIST = "META-INF/provider/provider.list"; static public Providers get() { return get(Thread.currentThread().getContextClassLoader()); } static public Providers get(ClassLoader classloader) { synchronized (providers) { Providers result = providers.get(classloader); if (result == null) { try { result = new Providers(classloader); } catch (IOException e) { throw new ProviderConfigurationException( "error creating providers", e); } providers.put(classloader, result); } return result; } } private ClassLoader loader; private List entries = new ArrayList(); private static final Logger Log = Logger .getLogger("de.intarsys.tools.provider"); protected Providers(ClassLoader cl) throws IOException { loader = cl; init(); } protected void addProvider(ProviderEntry entry) { for (ProviderEntry temp : entries) { if (temp.serviceName.equals(entry.serviceName) && temp.providerName.equals(entry.providerName)) { return; } } entries.add(entry); } private void init() throws IOException { Enumeration providerlistUrls; if (loader == null) { providerlistUrls = ClassLoader.getSystemResources(PROVIDERLIST); } else { providerlistUrls = loader.getResources(PROVIDERLIST); } while (providerlistUrls.hasMoreElements()) { URL providerlistUrl = providerlistUrls.nextElement(); InputStream is = null; try { is = providerlistUrl.openStream(); register(is); } finally { StreamTools.close(is); } } } public Iterator lookupProviders(final Class service) { return new Iterator() { private ProviderEntry current; private String serviceName = service.getName(); private Iterator it = entries.iterator(); @Override public boolean hasNext() { if (current != null) { return true; } while (it.hasNext()) { ProviderEntry temp = it.next(); if (serviceName.equals(temp.serviceName)) { current = temp; return true; } } return false; } @Override public S next() { if (!hasNext()) { throw new NoSuchElementException(); } ProviderEntry temp = current; current = null; if (temp.provider == null) { try { temp.provider = Class.forName(temp.providerName, true, loader).newInstance(); } catch (Throwable e) { Log.log(Level.FINEST, "loading provider failed", e); throw new ProviderConfigurationException("error loading " + temp.providerName, e); } } return (S) temp.provider; } @Override public void remove() { throw new UnsupportedOperationException(); } }; } public void register(InputStream is) throws IOException { BufferedReader r = null; try { r = new BufferedReader(new InputStreamReader(is, "utf-8")); while (registerLine(r)) ; } finally { StreamTools.close(r); } } protected boolean registerLine(BufferedReader r) throws IOException { String ln = r.readLine(); if (ln == null) { return false; } int ci = ln.indexOf(COMMENT); if (ci >= 0) ln = ln.substring(0, ci); ln = ln.trim(); if (ln.length() == 0) { return true; } String[] parts = ln.split(SEPARATOR); if (parts.length < 2) { return true; } ProviderEntry entry = new ProviderEntry(); entry.serviceName = parts[0].trim(); entry.providerName = parts[1].trim(); addProvider(entry); return true; } }