Details
-
Bug
-
Status: Closed
-
Major
-
Resolution: Not A Problem
-
None
-
None
-
None
-
None
-
Struts 2.1.6
xwork 2.0-SNAPSHOT
J2SE 1.6.0.10
TC 1.6
Description
xwork com.opensymphony.xwork2.config.ConfigurationManager code
/*** Get the current XWork configuration object. By default an instance of
DefaultConfiguration will be returned
- @see com.opensymphony.xwork2.config.impl.DefaultConfiguration
*/
public synchronized Configuration getConfiguration() {
if (configuration == null) {
setConfiguration(new DefaultConfiguration(defaultFrameworkBeanName));
try { configuration.reload(getConfigurationProviders()); }catch (ConfigurationException e) {
setConfiguration(null);
/****** xwork getConfigurationProviders code inlined so we can see whats going on *** - Get the current list of ConfigurationProviders. If no custom ConfigurationProviders have been added, this method
- will return a list containing only the default ConfigurationProvider, XMLConfigurationProvider. if a custom
- ConfigurationProvider has been added, then the XmlConfigurationProvider must be added by hand.
- </p>
- <p/>
- TODO: the lazy instantiation of XmlConfigurationProvider should be refactored to be elsewhere. the behavior described above seems unintuitive.
* - @return the list of registered ConfigurationProvider objects
- @see ConfigurationProvider
*/
public List<ConfigurationProvider> getConfigurationProviders() {
providerLock.lock();
tryUnknown macro: { if (configurationProviders.size() == 0) { configurationProviders.add(new XmlConfigurationProvider("xwork.xml", true)); } return configurationProviders; }finally
{ providerLock.unlock(); }}
{ conditionalReload(); }
***********/
throw e;
}
} else
return configuration;
}
//end configurationManager
//Here is com.opensymphony.xwork2.config.impl.DefaultConfigurationProvider
public synchronized List<PackageProvider> reloadContainer(List<ContainerProvider> providers) throws ConfigurationException {
ContainerProperties props = new ContainerProperties();
ContainerBuilder builder = new ContainerBuilder();
for (final ContainerProvider containerProvider : providers)
props.setConstants(builder);
//a quick recap of setConstants
/*public void setConstants(ContainerBuilder builder) {
//keySet appears to be empty so the iterator to key wont work here
for (Object keyobj : keySet())
}
*/
container = builder.create(false);
/*start code com.opensymphony.xwork2.inject.ConfigurationBuilder.create()
public Container create(boolean loadSingletons) {
ensureNotCreated();
created = true;
final ContainerImpl container = new ContainerImpl(
new HashMap<Key<?>, InternalFactory<?>>(factories));
if (loadSingletons) { //wont happen as this is always false
container.callInContext(new ContainerImpl.ContextualCallable<Void>() {
public Void call(InternalContext context) {
for (InternalFactory<?> factory : singletonFactories)
return null;
}
});
}
//final List<Class<?>> staticInjections = new ArrayList<Class<?>>();
//no effect as staticInjections are null at this point
container.injectStatics(staticInjections);
return container;
}
//end com.opensymphony.xwork2.inject.ConfigurationBuilder.create()
*/
setContext(container);
/******* setContext code inlined so we can see whats going on
protected ActionContext setContext(Container cont)
********/
// Set<String> getInstanceNames(Class<?> type);
objectFactory = container.getInstance(ObjectFactory.class);
//a not null objectFactory with no contained objects
// Process the configuration providers first (WARNING providers could be null!)
for (final ContainerProvider containerProvider : providers)
{
if (containerProvider instanceof PackageProvider)
}
// Then process any package providers from the plugins
//Container.getInstanceNames Set<String> getInstanceNames(Class<?> type);
/*com.opensymphony.xwork2.inject.ContainerImpl has getInstanceNames we can use
public Set<String> getInstanceNames(final Class<?> type)
*/
Set<String> packageProviderNames = container.getInstanceNames(PackageProvider.class);
if (packageProviderNames != null) {
for (String name : packageProviderNames)
}
rebuildRuntimeConfiguration();
} finally
return packageProviders;
//how does a factory for PackageProvider get created?
/* CAUTION members needs to contain the classnames for factory to create
<M extends Member & AnnotatedElement> void addInjectorsForMembers(
List<M> members, boolean statics, List<Injector> injectors,
InjectorFactory<M> injectorFactory) {
for (M member : members) {
if (isStatic(member) == statics) {
Inject inject = member.getAnnotation(Inject.class);
if (inject != null) {
try
catch (MissingDependencyException e) {
if (inject.required())
}
}
}
}
}
*/
//where is addInjectorsForMembers called?
/*addInjectorsForMembers is called as Injector parameter to method
void addInjectorsForMethods(Method[] methods, boolean statics,
List<Injector> injectors) {
addInjectorsForMembers(Arrays.asList(methods), statics, injectors,
new InjectorFactory<Method>() {
public Injector create(ContainerImpl container, Method method,
String name) throws MissingDependencyException
});
}
*/
OR addInjectorsForMember is called as parameter to Field
void addInjectorsForFields(Field[] fields, boolean statics,
List<Injector> injectors) {
addInjectorsForMembers(Arrays.asList(fields), statics, injectors,
new InjectorFactory<Field>() {
public Injector create(ContainerImpl container, Field field,
String name) throws MissingDependencyException
});
}
//where do the injectors come from
//they are called as a parameter to injectStatics here is the code:
void injectStatics(List<Class<?>> staticInjections) {
final List<Injector> injectors = new ArrayList<Injector>();
for (Class<?> clazz : staticInjections)
{ addInjectorsForFields(clazz.getDeclaredFields(), true, injectors); addInjectorsForMethods(clazz.getDeclaredMethods(), true, injectors); } callInContext(new ContextualCallable<Void>() {
public Void call(InternalContext context) {
for (Injector injector : injectors)
return null;
}
});
}
//the solution comes provided with test samples for xwork2
//com.opensymphony.xwork2.conf.XmlConfigurationProvider.java
String impl=java.util.Properties.getProperty("struts.convention.actionConfigBuilder");
Class clazz = new Class(impl);
//quick sanity check
if (clazz==null)
//if the instantiated class is null because of wrong name or not on classpath we should log the error!
Class cimpl = ClassLoaderUtil.loadClass(impl, clazz);
if (cimpl==null){ log.debug(impl+"class is not on classpath please put actionConfigBuilder class on classpath"); }
//if the instantiated class is null because of wrong name or not on classpath or CL couldnt find we should log the error!
/*the resourceName HAS TO BE PRECONFIGURED in context otherwise call to getResource on impl will fail
public static URL getResource(String resourceName, Class callingClass) {
URL url = Thread.currentThread().getContextClassLoader().getResource(resourceName);
if (url == null)
if (url == null) {
ClassLoader cl = callingClass.getClassLoader();
if (cl != null)
{ url = cl.getResource(resourceName); } }
*/
// Force loading of class to detect no class def found exceptions
try
catch(ClassNotFoundException cnfe)
{ log.debug("current CL cant locate class "+cimpl+"place class on CLASSPATH or configuration for plugin class is missing please try again"); } //now that you have the actionConfigBuilder Class built and the configuration is verified go ahead and inject
containerBuilder.injectStatics(cimpl);
HTH
Martin Gainty