org.apache.struts2.plexus.PlexusObjectFactory Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.struts2.plexus;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.Result;
import com.opensymphony.xwork2.config.ConfigurationException;
import com.opensymphony.xwork2.config.entities.ActionConfig;
import com.opensymphony.xwork2.config.entities.InterceptorConfig;
import com.opensymphony.xwork2.config.entities.ResultConfig;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.interceptor.Interceptor;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import com.opensymphony.xwork2.util.reflection.ReflectionProvider;
import com.opensymphony.xwork2.validator.Validator;
import org.codehaus.plexus.PlexusContainer;
import javax.servlet.ServletContext;
import java.util.HashMap;
import java.util.Map;
/**
*
* Plexus integration. You need three optional files: plexus-request.xml, plexus-session.xml, and
* plexus-application.xml.
*
*
* The syntax of these files is:
*
*
* <plexus>
* <components>
* <component>
* <role>com.acme.MyBean</role>
* <implementation>com.acme.MyBean|com.acme.MyBeanImpl</implementation>
* <componentComposer>field|setter|?</componentComposer>
* <requirements>
* <requirement>
* <role>com.acme.MyOtherBean</role>
* </requirement>
* </requirements>
* <configuration>
* <foo>123</foo>
* <bar>hello, world</bar>
* </configuration>
* </component>
* </components>
* </plexus>
*
*
* @author Emmanuel Venisse
*/
public class PlexusObjectFactory extends ObjectFactory {
private static final Logger LOG = LogManager.getLogger(PlexusObjectFactory.class);
private static final String PLEXUS_COMPONENT_TYPE = "plexus.component.type";
private PlexusContainer base;
private ReflectionProvider reflectionProvider;
public PlexusObjectFactory() {
}
@Inject
public void setReflectionProvider(ReflectionProvider reflectionProvider) {
this.reflectionProvider = reflectionProvider;
}
@Inject
public void setServletConfig(ServletContext servletContext) {
if (!PlexusLifecycleListener.isLoaded() || !PlexusFilter.isLoaded()) {
// uh oh! looks like the lifecycle listener wasn't installed. Let's inform the user
String message = "********** FATAL ERROR STARTING UP PLEXUS-STRUTS INTEGRATION **********\n" +
"Looks like the Plexus listener was not configured for your web app! \n" +
"You need to add the following to web.xml: \n" +
"\n" +
" \n" +
" \n" +
" plexus \n" +
" org.apache.struts2.plexus.PlexusFilter \n" +
" \n" +
"\n" +
"...\n" +
"\n" +
" \n" +
" \n" +
" plexus \n" +
" /* \n" +
" \n" +
"\n" +
"...\n" +
"\n" +
" \n" +
" org.apache.struts2.plexus.PlexusLifecycleListener \n" +
" ";
LOG.fatal(message);
return;
}
base = (PlexusContainer) servletContext.getAttribute(PlexusLifecycleListener.KEY);
}
/* (non-Javadoc)
* @see com.opensymphony.xwork2.ObjectFactory#buildAction(java.lang.String, java.lang.String, com.opensymphony.xwork2.config.entities.ActionConfig, java.util.Map)
*/
public Object buildAction(String actionName, String namespace, ActionConfig config, Map extraContext)
throws Exception {
if (extraContext == null) {
extraContext = new HashMap();
}
extraContext.put(PLEXUS_COMPONENT_TYPE, Action.class.getName());
return super.buildAction(actionName, namespace, config, extraContext);
}
/* (non-Javadoc)
* @see com.opensymphony.xwork2.ObjectFactory#buildInterceptor(com.opensymphony.xwork2.config.entities.InterceptorConfig, java.util.Map)
*/
public Interceptor buildInterceptor(InterceptorConfig interceptorConfig, Map interceptorRefParams)
throws ConfigurationException {
String interceptorClassName = interceptorConfig.getClassName();
Map thisInterceptorClassParams = interceptorConfig.getParams();
Map params = (thisInterceptorClassParams == null) ? new HashMap() : new HashMap(thisInterceptorClassParams);
params.putAll(interceptorRefParams);
String message;
Throwable cause;
try {
Map extraContext = new HashMap();
extraContext.put(PLEXUS_COMPONENT_TYPE, Interceptor.class.getName());
Interceptor interceptor = (Interceptor) buildBean(interceptorClassName, extraContext);
reflectionProvider.setProperties(params, interceptor);
interceptor.init();
return interceptor;
}
catch (InstantiationException e) {
cause = e;
message = "Unable to instantiate an instance of Interceptor class [" + interceptorClassName + "].";
}
catch (IllegalAccessException e) {
cause = e;
message = "IllegalAccessException while attempting to instantiate an instance of Interceptor class [" + interceptorClassName + "].";
}
catch (ClassCastException e) {
cause = e;
message = "Class [" + interceptorClassName + "] does not implement com.opensymphony.xwork2.interceptor.Interceptor";
}
catch (Exception e) {
cause = e;
message = "Caught Exception while registering Interceptor class " + interceptorClassName;
}
catch (NoClassDefFoundError e) {
cause = e;
message = "Could not load class " + interceptorClassName + ". Perhaps it exists but certain dependencies are not available?";
}
throw new ConfigurationException(message, cause);
}
/* (non-Javadoc)
* @see com.opensymphony.xwork2.ObjectFactory#buildResult(com.opensymphony.xwork2.config.entities.ResultConfig, java.util.Map)
*/
public Result buildResult(ResultConfig resultConfig, Map extraContext)
throws Exception {
if (extraContext == null) {
extraContext = new HashMap();
}
extraContext.put(PLEXUS_COMPONENT_TYPE, Result.class.getName());
return super.buildResult(resultConfig, extraContext);
}
/* (non-Javadoc)
* @see com.opensymphony.xwork2.ObjectFactory#buildValidator(java.lang.String, java.util.Map, java.util.Map)
*/
public Validator buildValidator(String className, Map params, Map extraContext)
throws Exception {
Map context = new HashMap();
context.put(PLEXUS_COMPONENT_TYPE, Validator.class.getName());
Validator validator = (Validator) buildBean(className, context);
reflectionProvider.setProperties(params, validator);
return validator;
}
/* (non-Javadoc)
* @see com.opensymphony.xwork2.ObjectFactory#buildBean(java.lang.Class, java.util.Map)
*/
public Object buildBean(Class clazz, Map extraContext)
throws Exception {
try {
return lookup(clazz.getName(), extraContext);
}
catch (Exception e) {
if (extraContext != null) {
String type = (String) extraContext.get(PLEXUS_COMPONENT_TYPE);
if (type != null) {
return lookup(type, clazz.getName(), extraContext);
}
}
throw e;
}
}
/* (non-Javadoc)
* @see com.opensymphony.xwork2.ObjectFactory#getClassInstance(java.lang.String)
*/
public Class getClassInstance(String className)
throws ClassNotFoundException {
PlexusContainer pc = PlexusThreadLocal.getPlexusContainer();
if (pc == null) {
pc = base;
}
try {
return pc.lookup(className).getClass();
}
catch (Exception e1) {
try {
return pc.lookup(Action.class.getName(), className).getClass();
}
catch (Exception e2) {
try {
return pc.lookup(Interceptor.class.getName(), className).getClass();
}
catch (Exception e3) {
try {
return pc.lookup(Validator.class.getName(), className).getClass();
}
catch (Exception e4) {
try {
return pc.lookup(Result.class.getName(), className).getClass();
}
catch (Exception e5) {
return super.getClassInstance(className);
}
}
}
}
}
}
/**
* Looks up an object
*
* @param role The role name
* @param extraContext The extra context
* @return The object
* @throws Exception If the lookup fails
*/
private Object lookup(String role, Map extraContext)
throws Exception {
return lookup(role, null, extraContext);
}
/**
* Looks up an object
*
* @param role The role name
* @param roleHint The role hint
* @param extraContext The extra context
* @return The object
* @throws Exception If the lookup fails
*/
private Object lookup(String role, String roleHint, Map extraContext)
throws Exception {
PlexusContainer pc = PlexusThreadLocal.getPlexusContainer();
if (pc == null) {
pc = base;
}
try {
return pc.lookup(role, roleHint);
}
catch (Exception e) {
if (LOG.isDebugEnabled()) {
LOG.debug("Can't load component (" + role + "/" + roleHint + ") with plexus, try now with struts.", e);
}
Object o = super.buildBean(super.getClassInstance(role), extraContext);
pc.autowire(o);
return o;
}
}
}