001: /*
002: * Copyright (c) 2003 The Visigoth Software Society. All rights
003: * reserved.
004: *
005: * Redistribution and use in source and binary forms, with or without
006: * modification, are permitted provided that the following conditions
007: * are met:
008: *
009: * 1. Redistributions of source code must retain the above copyright
010: * notice, this list of conditions and the following disclaimer.
011: *
012: * 2. Redistributions in binary form must reproduce the above copyright
013: * notice, this list of conditions and the following disclaimer in
014: * the documentation and/or other materials provided with the
015: * distribution.
016: *
017: * 3. The end-user documentation included with the redistribution, if
018: * any, must include the following acknowledgement:
019: * "This product includes software developed by the
020: * Visigoth Software Society (http://www.visigoths.org/)."
021: * Alternately, this acknowledgement may appear in the software itself,
022: * if and wherever such third-party acknowledgements normally appear.
023: *
024: * 4. Neither the name "FreeMarker", "Visigoth", nor any of the names of the
025: * project contributors may be used to endorse or promote products derived
026: * from this software without prior written permission. For written
027: * permission, please contact visigoths@visigoths.org.
028: *
029: * 5. Products derived from this software may not be called "FreeMarker" or "Visigoth"
030: * nor may "FreeMarker" or "Visigoth" appear in their names
031: * without prior written permission of the Visigoth Software Society.
032: *
033: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
034: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
035: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
036: * DISCLAIMED. IN NO EVENT SHALL THE VISIGOTH SOFTWARE SOCIETY OR
037: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
038: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
039: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
040: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
041: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
042: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
043: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
044: * SUCH DAMAGE.
045: * ====================================================================
046: *
047: * This software consists of voluntary contributions made by many
048: * individuals on behalf of the Visigoth Software Society. For more
049: * information on the Visigoth Software Society, please see
050: * http://www.visigoths.org/
051: */
052:
053: package freemarker.core;
054:
055: import java.util.List;
056:
057: import freemarker.ext.beans.BeansWrapper;
058: import freemarker.template.ObjectWrapper;
059: import freemarker.template.TemplateException;
060: import freemarker.template.TemplateMethodModelEx;
061: import freemarker.template.TemplateModel;
062: import freemarker.template.TemplateModelException;
063: import freemarker.template.TemplateScalarModel;
064: import freemarker.template.utility.ClassUtil;
065:
066: /**
067: * A built-in that allows us to instantiate an instance of a java class.
068: * Usage is something like:
069: * <#assign foobar = "foo.bar.MyClass"?new() />
070: */
071:
072: class NewBI extends BuiltIn {
073:
074: static final Class TM_CLASS = TemplateModel.class;
075: static final Class BEAN_MODEL_CLASS = freemarker.ext.beans.BeanModel.class;
076: static Class JYTHON_MODEL_CLASS;
077: static {
078: try {
079: JYTHON_MODEL_CLASS = Class
080: .forName("freemarker.ext.jython.JythonModel");
081: } catch (Throwable e) {
082: JYTHON_MODEL_CLASS = null;
083: }
084: }
085:
086: TemplateModel _getAsTemplateModel(Environment env)
087: throws TemplateException {
088: TemplateModel tm = target.getAsTemplateModel(env);
089: String classname = null;
090: try {
091: classname = ((TemplateScalarModel) tm).getAsString();
092: } catch (ClassCastException cce) {
093: invalidTypeException(tm, target, env, "string");
094: } catch (NullPointerException npe) {
095: throw new InvalidReferenceException(getStartLocation()
096: + "\nCould not resolve expression: " + target, env);
097: }
098: return new ConstructorFunction(classname, env);
099: }
100:
101: class ConstructorFunction implements TemplateMethodModelEx {
102:
103: private final Class cl;
104: private final Environment env;
105:
106: public ConstructorFunction(String classname, Environment env)
107: throws TemplateException {
108: this .env = env;
109: try {
110: cl = ClassUtil.forName(classname);
111: if (!TM_CLASS.isAssignableFrom(cl)) {
112: throw new TemplateException(
113: "Class "
114: + cl.getName()
115: + " does not implement freemarker.template.TemplateModel",
116: env);
117: }
118: if (BEAN_MODEL_CLASS.isAssignableFrom(cl)) {
119: throw new TemplateException(
120: "Bean Models cannot be instantiated using the ?new built-in",
121: env);
122: }
123: if (JYTHON_MODEL_CLASS != null
124: && JYTHON_MODEL_CLASS.isAssignableFrom(cl)) {
125: throw new TemplateException(
126: "Jython Models cannot be instantiated using the ?new built-in",
127: env);
128: }
129: } catch (ClassNotFoundException cnfe) {
130: throw new TemplateException(cnfe, env);
131: }
132: }
133:
134: public Object exec(List arguments)
135: throws TemplateModelException {
136: ObjectWrapper ow = env.getObjectWrapper();
137: BeansWrapper bw = ow instanceof BeansWrapper ? (BeansWrapper) ow
138: : BeansWrapper.getDefaultInstance();
139: return (TemplateModel) bw.newInstance(cl, arguments);
140: }
141: }
142: }
|