001: /*
002: * Copyright 2005 Joe Walker
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.directwebremoting.spring;
017:
018: import java.util.ArrayList;
019: import java.util.List;
020: import java.util.Map;
021:
022: import javax.servlet.ServletContext;
023: import javax.servlet.http.HttpServletRequest;
024:
025: import org.apache.commons.logging.LogFactory;
026: import org.apache.commons.logging.Log;
027: import org.directwebremoting.WebContextFactory;
028: import org.directwebremoting.create.AbstractCreator;
029: import org.directwebremoting.extend.Creator;
030: import org.directwebremoting.util.LocalUtil;
031: import org.directwebremoting.util.Messages;
032: import org.springframework.beans.factory.BeanFactory;
033: import org.springframework.context.support.ClassPathXmlApplicationContext;
034: import org.springframework.web.context.support.WebApplicationContextUtils;
035: import org.springframework.web.servlet.support.RequestContextUtils;
036:
037: /**
038: * A creator that relies on a spring bean factory.
039: * @author Joe Walker [joe at getahead dot ltd dot uk]
040: */
041: public class SpringCreator extends AbstractCreator implements Creator {
042: /**
043: * @return Returns the beanName.
044: */
045: public String getBeanName() {
046: return beanName;
047: }
048:
049: /**
050: * @param beanName The beanName to set.
051: */
052: public void setBeanName(String beanName) {
053: this .beanName = beanName;
054: }
055:
056: /**
057: * What sort of class do we create?
058: * @param classname The name of the class
059: */
060: public void setClass(String classname) {
061: try {
062: this .clazz = LocalUtil.classForName(classname);
063: } catch (ClassNotFoundException ex) {
064: throw new IllegalArgumentException(Messages.getString(
065: "Creator.ClassNotFound", classname));
066: }
067: }
068:
069: /* (non-Javadoc)
070: * @see org.directwebremoting.create.Creator#init(org.w3c.dom.Element)
071: */
072: @Override
073: public void setProperties(Map<String, String> params)
074: throws IllegalArgumentException {
075: List<String> locValues = new ArrayList<String>();
076:
077: for (Map.Entry<String, String> entry : params.entrySet()) {
078: String key = entry.getKey();
079: String value = entry.getValue();
080:
081: if (key.startsWith("location")) {
082: log.debug("Adding configLocation: " + value
083: + " from parameter: " + key);
084: locValues.add(value);
085: }
086: }
087:
088: configLocation = locValues
089: .toArray(new String[locValues.size()]);
090: }
091:
092: /* (non-Javadoc)
093: * @see org.directwebremoting.Creator#getType()
094: */
095: public Class<?> getType() {
096: if (clazz == null) {
097: try {
098: clazz = getInstance().getClass();
099: } catch (InstantiationException ex) {
100: log.error(
101: "Failed to instansiate object to detect type.",
102: ex);
103: return Object.class;
104: }
105: }
106:
107: return clazz;
108: }
109:
110: /* (non-Javadoc)
111: * @see org.directwebremoting.Creator#getInstance()
112: */
113: public Object getInstance() throws InstantiationException {
114: try {
115: if (overrideFactory != null) {
116: return overrideFactory.getBean(beanName);
117: }
118:
119: if (factory == null) {
120: factory = getBeanFactory();
121: }
122:
123: if (factory == null) {
124: log
125: .error("DWR can't find a spring config. See following info logs for solutions");
126: log
127: .info("- Option 1. In dwr.xml, <create creator='spring' ...> add <param name='location1' value='beans.xml'/> for each spring config file.");
128: log
129: .info("- Option 2. Use a spring org.springframework.web.context.ContextLoaderListener.");
130: log
131: .info("- Option 3. Call SpringCreator.setOverrideBeanFactory() from your web-app");
132: throw new InstantiationException(Messages
133: .getString("SpringCreator.MissingConfig"));
134: }
135:
136: return factory.getBean(beanName);
137: } catch (RuntimeException ex) {
138: throw ex;
139: } catch (Exception ex) {
140: log.error("Error", ex);
141: throw new InstantiationException(ex.toString());
142: }
143: }
144:
145: /**
146: * @return A found BeanFactory configuration
147: */
148: private BeanFactory getBeanFactory() {
149: // If someone has set a resource name then we need to load that.
150: if (configLocation != null && configLocation.length > 0) {
151: log
152: .info("Spring BeanFactory via ClassPathXmlApplicationContext using "
153: + configLocation.length
154: + "configLocations.");
155: return new ClassPathXmlApplicationContext(configLocation);
156: }
157:
158: ServletContext srvCtx = WebContextFactory.get()
159: .getServletContext();
160: HttpServletRequest request = WebContextFactory.get()
161: .getHttpServletRequest();
162:
163: if (request != null) {
164: return RequestContextUtils.getWebApplicationContext(
165: request, srvCtx);
166: } else {
167: return WebApplicationContextUtils
168: .getWebApplicationContext(srvCtx);
169: }
170: }
171:
172: /**
173: * Set a web-app wide BeanFactory.
174: * This method is misnamed (The parameter is a BeanFactory and not a
175: * XmlBeanFactory)
176: * @param factory The factory to set.
177: * @deprecated This method is misnamed use setOverrideBeanFactory
178: */
179: @Deprecated
180: public static void setXmlBeanFactory(BeanFactory factory) {
181: SpringCreator.overrideFactory = factory;
182: }
183:
184: /**
185: * Set a web-app wide BeanFactory.
186: * @param factory The factory to set.
187: */
188: public static void setOverrideBeanFactory(BeanFactory factory) {
189: SpringCreator.overrideFactory = factory;
190: }
191:
192: /**
193: * The name of the spring bean we want to create
194: */
195: private String beanName = null;
196:
197: /**
198: * The log stream
199: */
200: private static final Log log = LogFactory
201: .getLog(SpringCreator.class);
202:
203: /**
204: * The Spring beans factory from which we get our beans.
205: */
206: private BeanFactory factory = null;
207:
208: /**
209: * An web-app wide BeanFactory that we can use to override any calculated
210: * ones.
211: */
212: private static BeanFactory overrideFactory = null;
213:
214: /**
215: * The cached type of bean that we are creating
216: */
217: private Class<?> clazz = null;
218:
219: /**
220: * An array of locations to search through for a beans.xml file
221: */
222: private String[] configLocation = null;
223: }
|