// Licensed 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 net.sourceforge.eclipsejetty.starter.util.service;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.LinkedHashSet;
/**
* Common service utilities
*
* @author Manfred Hantschel
*/
public class ServiceUtils
{
/**
* Reads the services form the services file at META-INF/services/<type>
*
* @param type the type
* @return a collection of strings from the file
* @throws IOException on occasion
*/
public static Collection<String> getContributions(Class<?> type) throws IOException
{
Collection<String> results = new LinkedHashSet<String>();
Enumeration<URL> resources =
ServiceUtils.class.getClassLoader().getResources("META-INF/services/" + type.getName());
while (resources.hasMoreElements())
{
URL resource = resources.nextElement();
InputStream in = resource.openStream();
try
{
read(results, in);
}
finally
{
in.close();
}
}
return results;
}
/**
* Reads the services form the services file at META-INF/services/<type>. Instantiate the classes. Resolves
* constructor parameters from the specified {@link ServiceResolver}.
*
* @param type the type
* @param resolver the resolver
* @return the instantiates classes
* @throws IOException on occasion
*/
public static Collection<Object> instantiateContributions(Class<?> type, ServiceResolver resolver)
throws IOException
{
Collection<String> contributions = ServiceUtils.getContributions(type);
Collection<Object> results = new ArrayList<Object>();
for (String contribution : contributions)
{
results.add(instantiate(contribution, resolver));
}
return results;
}
private static Object instantiate(String contribution, ServiceResolver resolver)
{
try
{
Class<?> type = Class.forName(contribution);
Constructor<?>[] constructors = type.getConstructors();
if (constructors.length > 1)
{
throw new IllegalArgumentException(String.format(
"Failed to instantiate %s. There must be exactly one constructor", contribution));
}
Constructor<?> constructor = constructors[0];
Class<?>[] parameterTypes = constructor.getParameterTypes();
Object[] parameters = new Object[parameterTypes.length];
for (int i = 0; i < parameterTypes.length; i += 1)
{
parameters[i] = resolver.resolve(parameterTypes[i]);
}
return constructor.newInstance(parameters);
}
catch (SecurityException e)
{
throw new IllegalArgumentException(String.format("Failed to access %s for security reasons", contribution),
e);
}
catch (IllegalArgumentException e)
{
throw new IllegalArgumentException(String.format("Failed to instantiate %s", contribution), e);
}
catch (InstantiationException e)
{
throw new IllegalArgumentException(String.format("Failed to instantiate %s", contribution), e);
}
catch (IllegalAccessException e)
{
throw new IllegalArgumentException(String.format("Failed to access %s", contribution), e);
}
catch (InvocationTargetException e)
{
throw new IllegalArgumentException(String.format("Failed to instantiate %s", contribution), e);
}
catch (ClassNotFoundException e)
{
throw new IllegalArgumentException(
String.format("Failed to instantiate %s. Class not found", contribution), e);
}
}
private static void read(Collection<String> results, InputStream in) throws IOException
{
try
{
BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
try
{
String line;
while ((line = reader.readLine()) != null)
{
if (line.trim().length() == 0)
{
continue;
}
if (line.startsWith("#"))
{
continue;
}
results.add(line.trim());
}
}
finally
{
reader.close();
}
}
catch (UnsupportedEncodingException e)
{
throw new IllegalArgumentException("Danger! Danger! Universe imploding!", e);
}
}
}