001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.visualweb.insync.faces;
042:
043: import java.beans.BeanDescriptor;
044: import java.beans.BeanInfo;
045: import java.lang.reflect.Constructor;
046: import java.util.HashMap;
047:
048: import javax.faces.application.Application;
049: import javax.faces.component.UIComponent;
050: import javax.faces.context.FacesContext;
051: import com.sun.rave.designtime.Constants;
052: import org.netbeans.modules.visualweb.insync.Model;
053: import org.netbeans.modules.visualweb.insync.beans.BeanStructureScanner;
054: import org.netbeans.modules.visualweb.insync.beans.BeansUnit;
055: import org.netbeans.modules.visualweb.insync.java.JavaUnit;
056: import org.netbeans.modules.visualweb.insync.models.FacesModel;
057: import org.netbeans.modules.visualweb.jsfsupport.container.FacesContainer;
058:
059: /**
060: * An extended BeansUnit that is aware of JavaServer Faces features and designtime requirements and
061: * support. Provides access to the FacesContainer support provided in jsfsupport, as well as
062: * handling JSF related metadata queries.
063: *
064: * General JSF managed beans can be designed using an instance of this class. For page backing beans
065: * @see FacesPageUnit
066: *
067: * @author cquinn
068: */
069: public class FacesUnit extends BeansUnit {
070:
071: // FACES_IMPLICIT_OBJECTS var definition copied from com.sun.faces.el.ValueBindingImpl
072: // Not optimal, but their var is not visible to me, so I get I clone it for now. Will need to clean
073: // up as well as update as JSF updates this list :(
074: // TODO
075: // Array of faces implicit objects
076: protected static final String[] FACES_IMPLICIT_OBJECTS = {
077: "applicationScope", "sessionScope", "requestScope",
078: "facesContext", "cookies", "header", "headerValues",
079: "initParam", "param", "paramValues", "view" };
080:
081: protected static HashMap facesImplicitNamesMap;
082:
083: static {
084: facesImplicitNamesMap = new HashMap(
085: FACES_IMPLICIT_OBJECTS.length);
086: for (int i = 0; i < FACES_IMPLICIT_OBJECTS.length; i++) {
087: facesImplicitNamesMap.put(FACES_IMPLICIT_OBJECTS[i], "_"
088: + FACES_IMPLICIT_OBJECTS[i]);
089: }
090: }
091:
092: public static boolean isImplicitBeanName(String beanName) {
093: String implicitNameReplacement = (String) facesImplicitNamesMap
094: .get(beanName);
095: return implicitNameReplacement != null;
096: }
097:
098: public static String fixPossiblyImplicitBeanName(String beanName) {
099: String implicitNameReplacement = (String) facesImplicitNamesMap
100: .get(beanName);
101: if (implicitNameReplacement == null) {
102: return beanName;
103: }
104: return implicitNameReplacement;
105: }
106:
107: protected final FacesContainer container;
108: protected final String rootPackage;
109:
110: /**
111: * @param junit
112: * @param cl
113: * @param packageName
114: * @param rootPackage
115: * @param container
116: */
117: public FacesUnit(JavaUnit junit, ClassLoader cl,
118: String packageName, Model model, String rootPackage,
119: FacesContainer container) {
120: super (junit, cl, packageName, model);
121: this .rootPackage = rootPackage;
122: this .container = container;
123: }
124:
125: //------------------------------------------------------------------------------------ BeansUnit
126:
127: /**
128: * Return whether a bean described by a BeanInto is a faces component bean (UIComponent)
129: *
130: * @param beanInfo
131: * @return
132: */
133: public static final boolean isFacesBean(BeanInfo beanInfo) {
134: return UIComponent.class.isAssignableFrom(beanInfo
135: .getBeanDescriptor().getBeanClass());
136: }
137:
138: /**
139: * Return whether a bean described by a BeanInto is an html bean
140: *
141: * @param beanInfo
142: * @return
143: */
144: public static final boolean isHtmlBean(BeanInfo beanInfo) {
145: return beanInfo.getBeanDescriptor().getBeanClass().getName()
146: .startsWith(HtmlBean.PACKAGE);
147: }
148:
149: /**
150: * Get a given BeanDescriptor value by name from a BeanInfo
151: *
152: * @param bi
153: * @param name
154: * @return
155: */
156: public static final String getBeanDescriptorValue(BeanInfo bi,
157: String name) {
158: BeanDescriptor bd = bi.getBeanDescriptor();
159: if (bd != null) {
160: Object value = bd.getValue(name);
161: if (value instanceof String)
162: return (String) value;
163: }
164: return null;
165: }
166:
167: /**
168: * Get the tag name for a given bean type
169: *
170: * @param beanInfo
171: * @return
172: */
173: public static final String getBeanTagName(BeanInfo beanInfo) {
174: String btn = getBeanDescriptorValue(beanInfo,
175: Constants.BeanDescriptor.TAG_NAME);
176: if (btn == null && HtmlBean.isHtmlBean(beanInfo)) //!CQ TODO: should remove this when html beaninfos are avail
177: return HtmlBean.getBeanTagName(beanInfo);
178: return btn;
179: }
180:
181: /**
182: * Get the tag library URI for a given faces type
183: *
184: * @param beanInfo
185: * @return
186: */
187: public static final String getBeanTaglibUri(BeanInfo beanInfo) {
188: String btu = getBeanDescriptorValue(beanInfo,
189: Constants.BeanDescriptor.TAGLIB_URI);
190: if (btu == null && HtmlBean.isHtmlBean(beanInfo)) //!CQ TODO: should remove this when html beaninfos are avail
191: return HtmlBean.getBeanTaglibUri(beanInfo);
192: return btu;
193: }
194:
195: /**
196: * Get the recomended tag library prefix for a given faces type
197: *
198: * @param beanInfo
199: * @return
200: */
201: public static final String getBeanTaglibPrefix(BeanInfo beanInfo) {
202: String btp = getBeanDescriptorValue(beanInfo,
203: Constants.BeanDescriptor.TAGLIB_PREFIX);
204: if (btp == null && HtmlBean.isHtmlBean(beanInfo)) //!CQ TODO: should remove this when html beaninfos are avail
205: return HtmlBean.getBeanTaglibPrefix(beanInfo);
206: return btp;
207: }
208:
209: /**
210: * Get the tag name for a given faces type
211: *
212: * @param beanInfo
213: * @return
214: */
215: public static final String getBeanMarkupSection(BeanInfo beanInfo) {
216: String bms = getBeanDescriptorValue(beanInfo,
217: Constants.BeanDescriptor.MARKUP_SECTION);
218: //if (HtmlBean.isHtmlBean(beanInfo)) //!CQ TODO: should remove this when html beaninfos are avail
219: // return null;
220: return bms;
221: }
222:
223: /**
224: * Get the one unique FacesContext for this unit
225: *
226: * @return
227: */
228: public FacesContext getFacesContext() {
229: return container.getFacesContext();
230: }
231:
232: /**
233: * Get the one unique faces Application for this unit
234: *
235: * @return
236: */
237: public Application getFacesApplication() {
238: return getFacesContext().getApplication();
239: }
240:
241: /**
242: * @return the name of the runtime faces managed-bean for this unit's outer bean
243: */
244: public String getBeanName() {
245: String result = getBeanNameUnfixed();
246: result = fixPossiblyImplicitBeanName(result);
247: return result;
248: }
249:
250: /**
251: * @return the name of the runtime faces managed-bean for this unit's outer bean
252: */
253: public String getBeanNameUnfixed() {
254: if (packageName != null && packageName.length() > 0) {
255: String pkg = packageName;
256: if (pkg.startsWith(rootPackage)) {
257: pkg = pkg.substring(rootPackage.length());
258: if (pkg.startsWith("."))
259: pkg = pkg.substring(1);
260: }
261: if (pkg.length() > 0)
262: return fixPossiblyImplicitBeanName(pkg
263: .replace('.', '$')
264: + "$" + getThisClassName());
265: }
266: // just using the this-class name for no package, or a single level package
267: return fixPossiblyImplicitBeanName(getThisClassName());
268: }
269:
270: protected BeanStructureScanner getNewBeanStructureScanner() {
271: Class scannerClass = null;
272: for (int i = 0; i < FacesModel.managedBeanNames.length; i++) {
273: String name = FacesModel.managedBeanNames[i];
274: if (getBaseBeanClassName().equals(name)) {
275: scannerClass = FacesModel.managedBeanScannerTypes[i];
276: break;
277: }
278: }
279:
280: Constructor constructor = null;
281: // Get an instance of scanner based on my type or one of my ancestors,
282: // get the first constructor specialized for an instance of me
283: Class argumentType = getClass();
284: while (argumentType != null) {
285: try {
286: constructor = scannerClass
287: .getDeclaredConstructor(new Class[] { argumentType });
288: break;
289: } catch (NoSuchMethodException e1) {
290: argumentType = argumentType.getSuperclass();
291: }
292: }
293: BeanStructureScanner scanner;
294: try {
295: scanner = (BeanStructureScanner) constructor
296: .newInstance(new Object[] { this });
297: } catch (Exception e) {
298: scanner = null;
299: }
300: if (scanner == null)
301: // Always fall back to this
302: scanner = new BeanStructureScanner(this);
303: return scanner;
304: }
305: }
|