Skip to content

Commit

Permalink
Test Imported Service @iNJECTiON of various generic types.
Browse files Browse the repository at this point in the history
  • Loading branch information
lincolnthree committed Oct 16, 2013
1 parent d35c2f9 commit b54da94
Show file tree
Hide file tree
Showing 12 changed files with 367 additions and 80 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,23 @@ public <T> Imported<T> produceImported(InjectionPoint injectionPoint)
ParameterizedType parameterizedType = (ParameterizedType) type;

Type[] typeArguments = parameterizedType.getActualTypeArguments();
Class<T> importedType = (Class<T>) typeArguments[0];
Class<T> importedType = null;
Type argument = typeArguments[0];
if (argument instanceof Class)
{
importedType = (Class<T>) argument;
}
else if (argument instanceof ParameterizedType)
{
Type rawType = ((ParameterizedType) argument).getRawType();
if (rawType instanceof Class)
importedType = (Class<T>) rawType;
}
else
{
throw new IllegalStateException("Cannot inject a generic instance of type " + Imported.class.getName()
+ "<?> without specifying concrete generic types at injection point " + injectionPoint + ".");
}
return registry.getServices(importedType);
}
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

import javax.enterprise.inject.spi.Bean;
Expand All @@ -20,7 +18,6 @@
import org.jboss.forge.furnace.addons.Addon;
import org.jboss.forge.furnace.container.cdi.services.ExportedInstanceImpl;
import org.jboss.forge.furnace.lock.LockManager;
import org.jboss.forge.furnace.lock.LockMode;
import org.jboss.forge.furnace.spi.ExportedInstance;
import org.jboss.forge.furnace.spi.ServiceRegistry;
import org.jboss.forge.furnace.util.Addons;
Expand All @@ -42,7 +39,9 @@ public class ServiceRegistryImpl implements ServiceRegistry

private ClassLoader addonClassLoader;

private Map<String, Class<?>> classCache = new WeakHashMap<String, Class<?>>();
private Map<Integer, Class<?>> classCache = new WeakHashMap<Integer, Class<?>>();
private Map<Integer, ExportedInstance<?>> instanceCache = new WeakHashMap<Integer, ExportedInstance<?>>();
private Map<Integer, Set<ExportedInstance<?>>> instancesCache = new WeakHashMap<Integer, Set<ExportedInstance<?>>>();

public ServiceRegistryImpl(LockManager lock, Addon addon, BeanManager manager,
Set<Class<?>> services)
Expand All @@ -68,7 +67,7 @@ public <T> ExportedInstance<T> getExportedInstance(String clazz)
try
{
type = (Class<T>) loadAddonClass(clazz);
return getExportedInstance(type, type);
return getExportedInstance(type);
}
catch (ClassNotFoundException e)
{
Expand All @@ -77,68 +76,40 @@ public <T> ExportedInstance<T> getExportedInstance(String clazz)
}

@Override
public <T> ExportedInstance<T> getExportedInstance(Class<T> clazz)
{
return getExportedInstance(clazz, clazz);
}

/**
* @param requestedType interface
* @param actualType Implementation
* @return
*/
@SuppressWarnings("unchecked")
private <T> ExportedInstance<T> getExportedInstance(final Class<T> requestedType, final Class<T> actualType)
public <T> ExportedInstance<T> getExportedInstance(final Class<T> requestedType)
{
Assert.notNull(requestedType, "Requested Class type may not be null");
Assert.notNull(actualType, "Actual Class type may not be null");
Addons.waitUntilStarted(addon);
return lock.performLocked(LockMode.READ, new Callable<ExportedInstance<T>>()

ExportedInstance<T> result = (ExportedInstance<T>) instanceCache.get(requestedType.hashCode());
if (result == null)
{
@Override
public ExportedInstance<T> call() throws Exception
final Class<T> actualLoadedType;
try
{
/*
* Double checked waiting, with timeout to prevent complete deadlocks.
*/
Addons.waitUntilStarted(addon, 10, TimeUnit.SECONDS);
final Class<T> requestedLoadedType;
final Class<? extends T> actualLoadedType;
try
{
requestedLoadedType = loadAddonClass(requestedType);
}
catch (ClassNotFoundException cnfe)
{
log.fine("Class " + requestedType.getName() + " is not present in this addon [" + addon + "]");
return null;
}

try
{
actualLoadedType = loadAddonClass(actualType);
}
catch (ClassNotFoundException cnfe)
{
log.fine("Class " + actualType.getName() + " is not present in this addon [" + addon + "]");
return null;
}
actualLoadedType = loadAddonClass(requestedType);
}
catch (ClassNotFoundException cnfe)
{
log.fine("Class " + requestedType.getName() + " is not present in this addon [" + addon + "]");
return null;
}

ExportedInstance<T> result = null;
Set<Bean<?>> beans = manager.getBeans(requestedLoadedType, getQualifiersFrom(requestedLoadedType));
if (!beans.isEmpty())
{
result = new ExportedInstanceImpl<T>(
addon,
manager, (Bean<T>)
manager.resolve(beans),
requestedLoadedType,
actualLoadedType
);
}
return result;
Set<Bean<?>> beans = manager.getBeans(actualLoadedType, getQualifiersFrom(actualLoadedType));
if (!beans.isEmpty())
{
result = new ExportedInstanceImpl<T>(
addon,
manager, (Bean<T>)
manager.resolve(beans),
actualLoadedType,
actualLoadedType
);
instanceCache.put(requestedType.hashCode(), result);
}
});
}
return result;
}

@Override
Expand Down Expand Up @@ -193,12 +164,11 @@ public <T> Set<ExportedInstance<T>> getExportedInstances(String clazz)
}
}

@SuppressWarnings("unchecked")
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
public <T> Set<ExportedInstance<T>> getExportedInstances(Class<T> requestedType)
{
Addons.waitUntilStarted(addon);
Set<ExportedInstance<T>> result = new HashSet<ExportedInstance<T>>();

Class<T> requestedLoadedType;
try
Expand All @@ -208,27 +178,34 @@ public <T> Set<ExportedInstance<T>> getExportedInstances(Class<T> requestedType)
catch (ClassNotFoundException e)
{
log.fine("Class " + requestedType.getName() + " is not present in this addon [" + addon + "]");
return result;
return Collections.emptySet();
}

for (int i = 0; i < services.length; i++)
Set<ExportedInstance<T>> result = (Set) instancesCache.get(requestedLoadedType.hashCode());

if (result == null)
{
Class<?> type = services[i];
if (requestedLoadedType.isAssignableFrom(type))
result = new HashSet<ExportedInstance<T>>();
for (int i = 0; i < services.length; i++)
{
Set<Bean<?>> beans = manager.getBeans(type, getQualifiersFrom(type));
Class<? extends T> assignableClass = (Class<? extends T>) type;
for (Bean<?> bean : beans)
Class<?> type = services[i];
if (requestedLoadedType.isAssignableFrom(type))
{
result.add(new ExportedInstanceImpl<T>(
addon,
manager,
(Bean<T>) bean,
requestedLoadedType,
assignableClass
));

Set<Bean<?>> beans = manager.getBeans(type, getQualifiersFrom(type));
Class<? extends T> assignableClass = (Class<? extends T>) type;
for (Bean<?> bean : beans)
{
result.add(new ExportedInstanceImpl<T>(
addon,
manager,
(Bean<T>) bean,
requestedLoadedType,
assignableClass
));

}
}
instancesCache.put(requestedLoadedType.hashCode(), (Set) result);
}
}
return result;
Expand Down Expand Up @@ -273,12 +250,12 @@ private <T> Class<T> loadAddonClass(Class<T> actualType) throws ClassNotFoundExc

private Class<?> loadAddonClass(String className) throws ClassNotFoundException
{
Class<?> cached = classCache.get(className);
Class<?> cached = classCache.get(className.hashCode());
if (cached == null)
{
Class<?> result = Class.forName(className, false, addonClassLoader);
// potentially not thread-safe
classCache.put(className, result);
classCache.put(className.hashCode(), result);
cached = result;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import javax.enterprise.inject.spi.InjectionPoint;

import org.jboss.forge.furnace.addons.Addon;
import org.jboss.forge.furnace.addons.AddonFilter;
import org.jboss.forge.furnace.addons.AddonRegistry;
import org.jboss.forge.furnace.proxy.ForgeProxy;
import org.jboss.forge.furnace.proxy.Proxies;
Expand All @@ -16,6 +17,7 @@

public class ExportedInstanceLazyLoader implements ForgeProxy
{
private static final AddonFilter ALL_STARTED = AddonFilters.allStarted();
private final Class<?> serviceType;
private final AddonRegistry registry;
private final InjectionPoint injectionPoint;
Expand Down Expand Up @@ -70,7 +72,7 @@ public Object invoke(Object self, Method thisMethod, Method proceed, Object[] ar
private Object loadObject() throws Exception
{
Object result = null;
for (Addon addon : registry.getAddons(AddonFilters.allStarted()))
for (Addon addon : registry.getAddons(ALL_STARTED))
{
if (ClassLoaders.containsClass(addon.getClassLoader(), serviceType))
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Copyright 2013 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Eclipse Public License version 1.0, available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package test.org.jboss.forge.furnace.mocks.services;

/**
* @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
*
*/
public interface ParameterGenericType<T>
{

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Copyright 2013 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Eclipse Public License version 1.0, available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package test.org.jboss.forge.furnace.mocks.services;

/**
* @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
*
*/
public class ParameterGenericTypeImpl implements ParameterGenericType<String>
{

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Copyright 2013 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Eclipse Public License version 1.0, available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package test.org.jboss.forge.furnace.mocks.services;

/**
* @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
*
*/
public interface RawType
{

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Copyright 2013 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Eclipse Public License version 1.0, available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package test.org.jboss.forge.furnace.mocks.services;

/**
* @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
*
*/
public class RawTypeImpl implements RawType
{

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Copyright 2013 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Eclipse Public License version 1.0, available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package test.org.jboss.forge.furnace.mocks.services;

/**
* @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
*
*/
public interface TwoParameterGenericType<T, V>
{

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Copyright 2013 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Eclipse Public License version 1.0, available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package test.org.jboss.forge.furnace.mocks.services;

/**
* @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
*
*/
public class TwoParameterGenericTypeImpl implements TwoParameterGenericType<String, Integer>
{

}

0 comments on commit b54da94

Please sign in to comment.