001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.ejb.plugins.cmp.jdbc2;
023:
024: import org.jboss.ejb.plugins.cmp.bridge.EntityBridgeInvocationHandler;
025: import org.jboss.ejb.plugins.cmp.bridge.FieldBridge;
026: import org.jboss.ejb.plugins.cmp.jdbc2.bridge.JDBCEntityBridge2;
027: import org.jboss.ejb.plugins.cmp.jdbc2.bridge.EJBSelectBridge;
028: import org.jboss.ejb.plugins.cmp.jdbc2.schema.Schema;
029: import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCQueryMetaData;
030: import org.jboss.ejb.EntityContainer;
031: import org.jboss.proxy.compiler.Proxy;
032: import org.jboss.proxy.compiler.InvocationHandler;
033: import org.jboss.deployment.DeploymentException;
034:
035: import javax.ejb.FinderException;
036: import java.lang.reflect.Constructor;
037: import java.lang.reflect.Method;
038: import java.lang.reflect.Modifier;
039: import java.util.Map;
040: import java.util.HashMap;
041: import java.util.List;
042: import java.util.Collections;
043: import java.util.Iterator;
044: import java.util.Collection;
045:
046: /**
047: * @author <a href="mailto:alex@jboss.org">Alexey Loubyansky</a>
048: * @version <tt>$Revision: 57209 $</tt>
049: */
050: public class InstanceFactory {
051: private final Class beanClass;
052: private final Constructor beanProxyConstructor;
053: private final Map fieldMap;
054: private final Map selectorMap;
055:
056: public InstanceFactory(JDBCStoreManager2 manager,
057: JDBCEntityBridge2 entity) throws Exception {
058: EntityContainer theContainer = manager.getContainer();
059: beanClass = theContainer.getBeanClass();
060: fieldMap = createFieldMap(entity);
061: selectorMap = createSelectorMap(entity, manager
062: .getQueryFactory());
063: // use proxy generator to create one implementation
064: EntityBridgeInvocationHandler handler = new EntityBridgeInvocationHandler(
065: fieldMap, selectorMap, beanClass);
066: Class[] classes = new Class[] { beanClass };
067: ClassLoader classLoader = beanClass.getClassLoader();
068:
069: Object o = Proxy
070: .newProxyInstance(classLoader, classes, handler);
071:
072: // steal the constructor from the object
073: beanProxyConstructor = o.getClass().getConstructor(
074: new Class[] { InvocationHandler.class });
075:
076: // now create one to make sure everything is cool
077: newInstance();
078: }
079:
080: public void destroy() {
081: Proxy.forgetProxyForClass(beanClass);
082: }
083:
084: public Object newInstance() throws Exception {
085: EntityBridgeInvocationHandler handler = new EntityBridgeInvocationHandler(
086: fieldMap, selectorMap, beanClass);
087: return beanProxyConstructor
088: .newInstance(new Object[] { handler });
089: }
090:
091: private static Map getAbstractAccessors(Class beanClass) {
092: Method[] methods = beanClass.getMethods();
093: Map abstractAccessors = new HashMap(methods.length);
094:
095: for (int i = 0; i < methods.length; i++) {
096: if (Modifier.isAbstract(methods[i].getModifiers())) {
097: String methodName = methods[i].getName();
098: if (methodName.startsWith("get")
099: || methodName.startsWith("set")) {
100: abstractAccessors.put(methodName, methods[i]);
101: }
102: }
103: }
104: return abstractAccessors;
105: }
106:
107: private static Map createFieldMap(JDBCEntityBridge2 entityBridge)
108: throws DeploymentException {
109: Map abstractAccessors = getAbstractAccessors(entityBridge
110: .getMetaData().getEntityClass());
111:
112: List fields = entityBridge.getFields();
113: Map map = new HashMap(fields.size() * 2);
114: for (int i = 0; i < fields.size(); i++) {
115: FieldBridge field = (FieldBridge) fields.get(i);
116:
117: // get the names
118: String fieldName = field.getFieldName();
119: String fieldBaseName = Character.toUpperCase(fieldName
120: .charAt(0))
121: + fieldName.substring(1);
122: String getterName = "get" + fieldBaseName;
123: String setterName = "set" + fieldBaseName;
124:
125: // get the accessor methods
126: Method getterMethod = (Method) abstractAccessors
127: .get(getterName);
128: Method setterMethod = (Method) abstractAccessors
129: .get(setterName);
130:
131: // getters and setters must come in pairs
132: if (getterMethod != null && setterMethod == null) {
133: throw new DeploymentException(
134: "Getter was found but, no setter was found for field: "
135: + fieldName);
136: } else if (getterMethod == null && setterMethod != null) {
137: throw new DeploymentException(
138: "Setter was found but, no getter was found for field: "
139: + fieldName);
140: } else if (getterMethod != null && setterMethod != null) {
141: // add methods
142: map
143: .put(
144: getterMethod.getName(),
145: new EntityBridgeInvocationHandler.FieldGetInvoker(
146: field));
147: map
148: .put(
149: setterMethod.getName(),
150: new EntityBridgeInvocationHandler.FieldSetInvoker(
151: field));
152:
153: // remove the accessors (they have been used)
154: abstractAccessors.remove(getterName);
155: abstractAccessors.remove(setterName);
156: }
157: }
158: return Collections.unmodifiableMap(map);
159: }
160:
161: private static Map createSelectorMap(
162: JDBCEntityBridge2 entityBridge, QueryFactory queryFactory)
163: throws DeploymentException {
164: Collection queries = entityBridge.getMetaData().getQueries();
165: Map selectorsByMethod = new HashMap(queries.size());
166: Iterator definedFinders = queries.iterator();
167: while (definedFinders.hasNext()) {
168: JDBCQueryMetaData metadata = (JDBCQueryMetaData) definedFinders
169: .next();
170: if (metadata.getMethod().getName().startsWith("ejbSelect")) {
171: try {
172: QueryCommand queryCommand = queryFactory
173: .getQueryCommand(metadata.getMethod());
174: Schema schema = ((JDBCStoreManager2) entityBridge
175: .getManager()).getSchema();
176: EJBSelectBridge ejbSelectBridge = new EJBSelectBridge(
177: entityBridge.getContainer(), schema,
178: metadata, queryCommand);
179: selectorsByMethod.put(metadata.getMethod(),
180: ejbSelectBridge);
181: } catch (FinderException e) {
182: throw new DeploymentException(e.getMessage());
183: }
184: }
185: }
186:
187: return selectorsByMethod;
188: }
189: }
|