001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.webbeans.cfg;
031:
032: import com.caucho.config.*;
033: import com.caucho.config.j2ee.*;
034: import com.caucho.config.program.*;
035: import com.caucho.config.types.*;
036: import com.caucho.ejb.cfg.*;
037: import com.caucho.ejb3.gen.*;
038: import com.caucho.util.*;
039: import com.caucho.webbeans.*;
040: import com.caucho.webbeans.component.*;
041: import com.caucho.webbeans.context.*;
042: import com.caucho.webbeans.manager.WebBeansContainer;
043:
044: import java.beans.*;
045: import java.lang.reflect.*;
046: import java.lang.annotation.*;
047: import java.util.ArrayList;
048:
049: import javax.annotation.*;
050: import javax.ejb.*;
051: import javax.webbeans.*;
052:
053: /**
054: * Configuration for the xml web bean component.
055: */
056: public class WbComponentConfig {
057: private static final L10N L = new L10N(WbComponentConfig.class);
058:
059: private static final Object[] NULL_ARGS = new Object[0];
060:
061: private WbWebBeans _webbeans;
062:
063: private Class _cl;
064:
065: private WbComponentType _type;
066:
067: private String _name;
068:
069: private ArrayList<WbBinding> _bindingList = new ArrayList<WbBinding>();
070:
071: private Class _scope;
072:
073: private ContainerProgram _init;
074:
075: protected ComponentImpl _comp;
076:
077: public WbComponentConfig() {
078: _webbeans = WebBeansContainer.create().getWbWebBeans();
079: }
080:
081: public WbComponentConfig(WbWebBeans webbeans) {
082: _webbeans = webbeans;
083: }
084:
085: /**
086: * Returns the component's EL binding name.
087: */
088: public void setName(String name) {
089: _name = name;
090:
091: WbBinding binding = new WbBinding();
092: binding.setClass(Named.class);
093: binding.addValue("value", name);
094:
095: _bindingList.add(binding);
096: }
097:
098: /**
099: * Gets the component's EL binding name.
100: */
101: public String getName() {
102: return _name;
103: }
104:
105: /**
106: * Returns the mbean-name
107: */
108: public String getMBeanName() {
109: return null;
110: }
111:
112: /**
113: * Sets the component type.
114: */
115: public void setType(Class type) {
116: if (!type.isAnnotationPresent(ComponentType.class))
117: throw new ConfigException(
118: L
119: .l(
120: "'{0}' is an invalid component annotation. Component types must be annotated by @ComponentType.",
121: type.getName()));
122:
123: _type = _webbeans.createComponentType(type);
124: }
125:
126: /**
127: * Gets the component type.
128: */
129: public WbComponentType getType() {
130: return _type;
131: }
132:
133: /**
134: * Sets the component type.
135: */
136: public void setComponentType(WbComponentType type) {
137: if (type == null)
138: throw new NullPointerException();
139:
140: _type = type;
141: }
142:
143: /**
144: * Sets the component type.
145: */
146: public WbComponentType getComponentType() {
147: return _type;
148: }
149:
150: /**
151: * Sets the component implementation class.
152: */
153: public void setClass(Class cl) {
154: _cl = cl;
155:
156: if (_name == null)
157: _name = Introspector.decapitalize(cl.getSimpleName());
158: }
159:
160: public Class getClassType() {
161: return _cl;
162: }
163:
164: public ComponentImpl getComponent() {
165: return _comp;
166: }
167:
168: /**
169: * Adds a component binding.
170: */
171: public void addBinding(WbBinding binding) {
172: _bindingList.add(binding);
173: }
174:
175: public ArrayList<WbBinding> getBindingList() {
176: return _bindingList;
177: }
178:
179: /**
180: * Sets the scope attribute.
181: */
182: public void setScope(String scope) {
183: if ("singleton".equals(scope))
184: _scope = Singleton.class;
185: else if ("dependent".equals(scope))
186: _scope = Dependent.class;
187: else if ("request".equals(scope))
188: _scope = RequestScoped.class;
189: else if ("session".equals(scope))
190: _scope = SessionScoped.class;
191: else if ("application".equals(scope))
192: _scope = ApplicationScoped.class;
193: else if ("conversation".equals(scope))
194: _scope = ConversationScoped.class;
195: else {
196: Class cl = null;
197:
198: try {
199: ClassLoader loader = Thread.currentThread()
200: .getContextClassLoader();
201:
202: cl = Class.forName(scope, false, loader);
203: } catch (ClassNotFoundException e) {
204: }
205:
206: if (cl == null)
207: throw new ConfigException(
208: L
209: .l("'{0}' is an invalid scope. The scope must be a valid @ScopeType annotation."));
210:
211: if (!Annotation.class.isAssignableFrom(cl))
212: throw new ConfigException(
213: L
214: .l("'{0}' is an invalid scope. The scope must be a valid @ScopeType annotation."));
215:
216: if (!cl.isAnnotationPresent(ScopeType.class))
217: throw new ConfigException(
218: L
219: .l("'{0}' is an invalid scope. The scope must be a valid @ScopeType annotation."));
220:
221: _scope = cl;
222: }
223: }
224:
225: /**
226: * Sets the init program.
227: */
228: public void setInit(ContainerProgram init) {
229: if (_init == null)
230: _init = new ContainerProgram();
231:
232: _init.addProgram(init);
233: }
234:
235: public ContainerProgram getInit() {
236: return _init;
237: }
238:
239: /**
240: * Adds an init property
241: */
242: public void addStringProperty(String name, String value) {
243: if (_init == null)
244: _init = new ContainerProgram();
245:
246: _init.addProgram(new PropertyStringProgram(name, value));
247: }
248:
249: /**
250: * Adds an init property
251: */
252: public void addOptionalStringProperty(String name, String value) {
253: if (_init == null)
254: _init = new ContainerProgram();
255:
256: _init.addProgram(0,
257: new PropertyStringProgram(name, value, true));
258: }
259:
260: /**
261: * Returns the configured component factory.
262: */
263: public ComponentImpl getComponentFactory() {
264: return _comp;
265: }
266:
267: /**
268: * Initialization.
269: */
270: @PostConstruct
271: public void init() {
272: if (_cl == null)
273: throw new ConfigException(L.l(
274: "<{0}> requires a class attribute", getTagName()));
275:
276: if (_cl.isAnnotationPresent(Stateless.class)) {
277: StatelessBeanConfig cfg = new StatelessBeanConfig(this );
278: cfg.init();
279: return;
280: } else if (_cl.isAnnotationPresent(Stateful.class)) {
281: StatefulBeanConfig cfg = new StatefulBeanConfig(this );
282: cfg.init();
283: return;
284: }
285:
286: introspect();
287:
288: ClassComponent comp;
289:
290: if (Singleton.class.equals(_scope))
291: comp = new SingletonClassComponent(_webbeans);
292: else
293: comp = new ClassComponent(_webbeans);
294:
295: comp.setInstanceClass(_cl);
296: comp.setTargetType(_cl);
297:
298: if (_name != null) {
299: comp.setName(_name);
300:
301: addOptionalStringProperty("name", _name);
302: }
303:
304: if (getMBeanName() != null)
305: comp.setMBeanName(getMBeanName());
306:
307: comp.setBindingList(_bindingList);
308:
309: if (_type != null)
310: comp.setType(_type);
311: else
312: comp
313: .setType(_webbeans
314: .createComponentType(Component.class));
315:
316: if (_scope != null)
317: comp.setScope(_webbeans.getScopeContext(_scope));
318:
319: if (_init != null)
320: comp.setInit(_init);
321:
322: _comp = comp;
323:
324: introspectPostInit();
325:
326: comp.init();
327:
328: deploy();
329: }
330:
331: /**
332: * Returns the XML tag name for debugging.
333: */
334: protected String getTagName() {
335: return "component";
336: }
337:
338: /**
339: * Introspection after the init has been set and before the @PostConstruct
340: * for additional interception
341: */
342: protected void introspectPostInit() {
343: }
344:
345: protected void deploy() {
346: if (_comp != null) {
347: _webbeans.addWbComponent(_comp);
348: _webbeans.init();
349: }
350: }
351:
352: public Object getObject() {
353: return _comp.get();
354: }
355:
356: private void introspect() {
357: if (_scope == null) {
358: for (Annotation ann : _cl.getDeclaredAnnotations()) {
359: if (ann.annotationType().isAnnotationPresent(
360: ScopeType.class)) {
361: if (_scope != null) {
362: throw new ConfigException(
363: L
364: .l(
365: "{0}: multiple scope annotations are forbidden ({1} and {2}).",
366: _cl.getName(),
367: _scope.getSimpleName(),
368: ann
369: .annotationType()
370: .getSimpleName()));
371: }
372:
373: _scope = ann.annotationType();
374: }
375: }
376: }
377: }
378: }
|