use of lucee.transformer.library.tag.TagLibTagAttr in project Lucee by lucee.
the class CFTag method validateAttributes.
private static void validateAttributes(Component cfc, StructImpl attributesScope, String tagName) throws ApplicationException, ExpressionException {
TagLibTag tag = getAttributeRequirments(cfc, false);
if (tag == null)
return;
if (tag.getAttributeType() == TagLibTag.ATTRIBUTE_TYPE_FIXED || tag.getAttributeType() == TagLibTag.ATTRIBUTE_TYPE_MIXED) {
Iterator<Entry<String, TagLibTagAttr>> it = tag.getAttributes().entrySet().iterator();
int count = 0;
Collection.Key key;
TagLibTagAttr attr;
Object value;
Entry<String, TagLibTagAttr> entry;
// check existing attributes
while (it.hasNext()) {
entry = it.next();
count++;
key = KeyImpl.toKey(entry.getKey(), null);
attr = entry.getValue();
value = attributesScope.get(key, null);
// check alias
if (value == null) {
String[] alias = attr.getAlias();
if (!ArrayUtil.isEmpty(alias))
for (int i = 0; i < alias.length; i++) {
value = attributesScope.get(KeyImpl.toKey(alias[i], null), null);
if (value != null)
break;
}
}
if (value == null) {
if (attr.getDefaultValue() != null) {
value = attr.getDefaultValue();
attributesScope.setEL(key, value);
} else if (attr.isRequired())
throw new ApplicationException("attribute [" + key.getString() + "] is required for tag [" + tagName + "]");
}
if (value != null) {
if (!Decision.isCastableTo(attr.getType(), value, true, true, -1))
throw new CasterException(createMessage(attr.getType(), value));
}
}
// check if there are attributes not supported
if (tag.getAttributeType() == TagLibTag.ATTRIBUTE_TYPE_FIXED && count < attributesScope.size()) {
Collection.Key[] keys = attributesScope.keys();
for (int i = 0; i < keys.length; i++) {
if (tag.getAttribute(keys[i].getLowerString(), true) == null)
throw new ApplicationException("attribute [" + keys[i].getString() + "] is not supported for tag [" + tagName + "]");
}
// Attribute susi is not allowed for tag cfmail
}
}
}
use of lucee.transformer.library.tag.TagLibTagAttr in project Lucee by lucee.
the class TagHelper method writeOut.
/**
* writes out the tag
* @param tag
* @param bc
* @param doReuse
* @throws TransformerException
* @throws BundleException
* @throws ClassException
*/
public static void writeOut(Tag tag, BytecodeContext bc, boolean doReuse, final FlowControlFinal fcf) throws TransformerException {
final GeneratorAdapter adapter = bc.getAdapter();
final TagLibTag tlt = tag.getTagLibTag();
final ClassDefinition cd = tlt.getTagClassDefinition();
final boolean fromBundle = cd.getName() != null;
final Type currType;
if (fromBundle) {
try {
if (Reflector.isInstaneOf(cd.getClazz(), BodyTag.class))
currType = BODY_TAG;
else
currType = TAG;
} catch (Exception e) {
if (e instanceof TransformerException)
throw (TransformerException) e;
throw new TransformerException(e, tag.getStart());
}
} else
currType = getTagType(tag);
final int currLocal = adapter.newLocal(currType);
Label tagBegin = new Label();
Label tagEnd = new Label();
ExpressionUtil.visitLine(bc, tag.getStart());
// TODO adapter.visitLocalVariable("tag", "L"+currType.getInternalName()+";", null, tagBegin, tagEnd, currLocal);
adapter.visitLabel(tagBegin);
// tag=pc.use(String tagClassName,String tagBundleName, String tagBundleVersion, String fullname,int attrType) throws PageException {
adapter.loadArg(0);
adapter.checkCast(Types.PAGE_CONTEXT_IMPL);
adapter.push(cd.getClassName());
// has bundle info/version
if (fromBundle) {
// name
adapter.push(cd.getName());
// version
if (cd.getVersion() != null)
adapter.push(cd.getVersionAsString());
else
ASMConstants.NULL(adapter);
}
adapter.push(tlt.getFullName());
adapter.push(tlt.getAttributeType());
adapter.invokeVirtual(Types.PAGE_CONTEXT_IMPL, fromBundle ? USE5 : USE3);
if (currType != TAG)
adapter.checkCast(currType);
adapter.storeLocal(currLocal);
TryFinallyVisitor outerTcfv = new TryFinallyVisitor(new OnFinally() {
@Override
public void _writeOut(BytecodeContext bc) {
adapter.loadArg(0);
adapter.checkCast(Types.PAGE_CONTEXT_IMPL);
adapter.loadLocal(currLocal);
if (cd.getName() != null) {
adapter.push(cd.getName());
if (cd.getVersion() != null)
adapter.push(cd.getVersionAsString());
else
ASMConstants.NULL(adapter);
}
adapter.invokeVirtual(Types.PAGE_CONTEXT_IMPL, fromBundle ? RE_USE3 : RE_USE1);
}
}, null);
if (doReuse)
outerTcfv.visitTryBegin(bc);
// appendix
if (tlt.hasAppendix()) {
adapter.loadLocal(currLocal);
adapter.push(tag.getAppendix());
if (// PageContextUtil.setAppendix(tag,appendix)
fromBundle)
ASMUtil.invoke(ASMUtil.STATIC, adapter, Types.TAG_UTIL, SET_APPENDIX2);
else
// tag.setAppendix(appendix)
ASMUtil.invoke(ASMUtil.VIRTUAL, adapter, currType, SET_APPENDIX1);
}
// hasBody
boolean hasBody = tag.getBody() != null;
if (tlt.isBodyFree() && tlt.hasBodyMethodExists()) {
adapter.loadLocal(currLocal);
adapter.push(hasBody);
if (// PageContextUtil.setAppendix(tag,appendix)
fromBundle)
ASMUtil.invoke(ASMUtil.STATIC, adapter, Types.TAG_UTIL, HAS_BODY2);
else
// tag.setAppendix(appendix)
ASMUtil.invoke(ASMUtil.VIRTUAL, adapter, currType, HAS_BODY1);
}
// default attributes (get overwritten by attributeCollection because of that set before)
setAttributes(bc, tag, currLocal, currType, true, fromBundle);
// attributeCollection
Attribute attrColl = tag.getAttribute("attributecollection");
if (attrColl != null) {
int attrType = tag.getTagLibTag().getAttributeType();
if (TagLibTag.ATTRIBUTE_TYPE_NONAME != attrType) {
tag.removeAttribute("attributecollection");
// TagUtil.setAttributeCollection(Tag, Struct)
adapter.loadArg(0);
adapter.loadLocal(currLocal);
if (currType != TAG)
adapter.cast(currType, TAG);
// /
TagLibTagAttr[] missings = tag.getMissingAttributes();
if (!ArrayUtil.isEmpty(missings)) {
ArrayVisitor av = new ArrayVisitor();
av.visitBegin(adapter, MISSING_ATTRIBUTE, missings.length);
int count = 0;
TagLibTagAttr miss;
for (int i = 0; i < missings.length; i++) {
miss = missings[i];
av.visitBeginItem(adapter, count++);
bc.getFactory().registerKey(bc, bc.getFactory().createLitString(miss.getName()), false);
adapter.push(miss.getType());
if (ArrayUtil.isEmpty(miss.getAlias()))
adapter.invokeStatic(MISSING_ATTRIBUTE, NEW_INSTANCE_MAX2);
else {
new LiteralStringArray(bc.getFactory(), miss.getAlias()).writeOut(bc, Expression.MODE_REF);
adapter.invokeStatic(MISSING_ATTRIBUTE, NEW_INSTANCE_MAX3);
}
av.visitEndItem(bc.getAdapter());
}
av.visitEnd();
} else {
ASMConstants.NULL(adapter);
}
// /
attrColl.getValue().writeOut(bc, Expression.MODE_REF);
adapter.push(attrType);
adapter.invokeStatic(TAG_UTIL, SET_ATTRIBUTE_COLLECTION);
}
}
// metadata
Attribute attr;
Map<String, Attribute> metadata = tag.getMetaData();
if (metadata != null) {
Iterator<Attribute> it = metadata.values().iterator();
while (it.hasNext()) {
attr = it.next();
adapter.loadLocal(currLocal);
adapter.push(attr.getName());
attr.getValue().writeOut(bc, Expression.MODE_REF);
if (fromBundle)
ASMUtil.invoke(ASMUtil.STATIC, adapter, Types.TAG_UTIL, SET_META_DATA3);
else
ASMUtil.invoke(ASMUtil.VIRTUAL, adapter, currType, SET_META_DATA2);
}
}
// set attributes
setAttributes(bc, tag, currLocal, currType, false, fromBundle);
// Body
if (hasBody) {
final int state = adapter.newLocal(Types.INT_VALUE);
// int state=tag.doStartTag();
adapter.loadLocal(currLocal);
ASMUtil.invoke(fromBundle ? ASMUtil.INTERFACE : ASMUtil.VIRTUAL, adapter, currType, DO_START_TAG);
// adapter.invokeVirtual(currType, DO_START_TAG);
adapter.storeLocal(state);
// if (state!=Tag.SKIP_BODY)
Label endBody = new Label();
adapter.loadLocal(state);
adapter.push(javax.servlet.jsp.tagext.Tag.SKIP_BODY);
adapter.visitJumpInsn(Opcodes.IF_ICMPEQ, endBody);
// pc.initBody(tag, state);
adapter.loadArg(0);
adapter.loadLocal(currLocal);
adapter.loadLocal(state);
adapter.invokeVirtual(Types.PAGE_CONTEXT, INIT_BODY);
OnFinally onFinally = new OnFinally() {
@Override
public void _writeOut(BytecodeContext bc) {
Label endIf = new Label();
/*if(tlt.handleException() && fcf!=null && fcf.getAfterFinalGOTOLabel()!=null){
ASMUtil.visitLabel(adapter, fcf.getFinalEntryLabel());
}*/
adapter.loadLocal(state);
adapter.push(javax.servlet.jsp.tagext.Tag.EVAL_BODY_INCLUDE);
adapter.visitJumpInsn(Opcodes.IF_ICMPEQ, endIf);
// ... pc.popBody();
adapter.loadArg(0);
adapter.invokeVirtual(Types.PAGE_CONTEXT, POP_BODY);
adapter.pop();
adapter.visitLabel(endIf);
// tag.doFinally();
if (tlt.handleException()) {
adapter.loadLocal(currLocal);
ASMUtil.invoke(fromBundle ? ASMUtil.INTERFACE : ASMUtil.VIRTUAL, adapter, currType, DO_FINALLY);
// adapter.invokeVirtual(currType, DO_FINALLY);
}
// GOTO after execution body, used when a continue/break was called before
/*if(fcf!=null) {
Label l = fcf.getAfterFinalGOTOLabel();
if(l!=null)adapter.visitJumpInsn(Opcodes.GOTO, l);
}*/
}
};
if (tlt.handleException()) {
TryCatchFinallyVisitor tcfv = new TryCatchFinallyVisitor(onFinally, fcf);
tcfv.visitTryBegin(bc);
doTry(bc, adapter, tag, currLocal, currType, fromBundle);
int t = tcfv.visitTryEndCatchBeging(bc);
// tag.doCatch(t);
adapter.loadLocal(currLocal);
adapter.loadLocal(t);
// adapter.visitVarInsn(Opcodes.ALOAD,t);
ASMUtil.invoke(fromBundle ? ASMUtil.INTERFACE : ASMUtil.VIRTUAL, adapter, currType, DO_CATCH);
// adapter.invokeVirtual(currType, DO_CATCH);
tcfv.visitCatchEnd(bc);
} else {
TryFinallyVisitor tfv = new TryFinallyVisitor(onFinally, fcf);
tfv.visitTryBegin(bc);
doTry(bc, adapter, tag, currLocal, currType, fromBundle);
tfv.visitTryEnd(bc);
}
adapter.visitLabel(endBody);
} else {
// tag.doStartTag();
adapter.loadLocal(currLocal);
ASMUtil.invoke(fromBundle ? ASMUtil.INTERFACE : ASMUtil.VIRTUAL, adapter, currType, DO_START_TAG);
// adapter.invokeVirtual(currType, DO_START_TAG);
adapter.pop();
}
// if (tag.doEndTag()==Tag.SKIP_PAGE) throw new Abort(0<!-- SCOPE_PAGE -->);
Label endDoEndTag = new Label();
adapter.loadLocal(currLocal);
ASMUtil.invoke(fromBundle ? ASMUtil.INTERFACE : ASMUtil.VIRTUAL, adapter, currType, DO_END_TAG);
// adapter.invokeVirtual(currType, DO_END_TAG);
adapter.push(javax.servlet.jsp.tagext.Tag.SKIP_PAGE);
adapter.visitJumpInsn(Opcodes.IF_ICMPNE, endDoEndTag);
adapter.push(Abort.SCOPE_PAGE);
adapter.invokeStatic(ABORT, NEW_INSTANCE);
adapter.throwException();
adapter.visitLabel(endDoEndTag);
if (doReuse) {
// } finally{pc.reuse(tag);}
outerTcfv.visitTryEnd(bc);
}
adapter.visitLabel(tagEnd);
ExpressionUtil.visitLine(bc, tag.getEnd());
}
use of lucee.transformer.library.tag.TagLibTagAttr in project Lucee by lucee.
the class CFMLTransformer method attributes.
/**
* Liest die Attribute eines Tags ein, dies Abhaengig von der Definition innerhalb der Tag-Lib.
* Hierbei unterscheiden wir vier verschiedene Arten von Attributen:<br>
* <ul>
* <li>FIX: Definierte Attribute Fix, fuer jedes Attribut ist definiert ob es required ist oder nicht (gleich wie JSP). </li>
* <li>DYNAMIC: Die Attribute des Tag sind frei, keine Namen sind vorgegeben.
* Es kann aber definiert sein wieviele Attribute maximal und minimal verwendetet werden duerfen.</li>
* <li>FULLDYNAMIC: Gleich wie DYNAMIC, jedoch kann der Name des Attribut auch ein dynamischer Wert sein (wie bei cfset).</li>
* <li>NONAME: Ein Tag welches nur ein Attribut besitzt ohne Name, sondern einfach nur mit einem Attribut Wert</li>
* </ul>
* <br />
* EBNF:<br />
* <code>({spaces attribute} "/>" | {spaces attribute} ">") | attribute-value;(* Welcher Teil der "oder" Bedingung ausgefuehrt wird, ist abhaengig von der Tag Attribute Definition in der Tag Lib. *)</code>
* @param tag
* @param parent
* @throws TemplateException
*/
public static void attributes(TagData data, TagLibTag tag, Tag parent) throws TemplateException {
int type = tag.getAttributeType();
int start = data.srcCode.getPos();
// Tag with attribute names
if (type != TagLibTag.ATTRIBUTE_TYPE_NONAME) {
try {
int min = tag.getMin();
int max = tag.getMax();
int count = 0;
ArrayList<String> args = new ArrayList<String>();
RefBoolean allowDefaultValue = new RefBooleanImpl(tag.getDefaultAttribute() != null);
while (data.srcCode.isValidIndex()) {
data.srcCode.removeSpace();
// if no more attributes break
if (data.srcCode.isCurrent('/') || data.srcCode.isCurrent('>'))
break;
parent.addAttribute(attribute(data, tag, args, allowDefaultValue));
count++;
}
// set default values
if (tag.hasDefaultValue()) {
Map<String, TagLibTagAttr> hash = tag.getAttributes();
Iterator<Entry<String, TagLibTagAttr>> it = hash.entrySet().iterator();
Entry<String, TagLibTagAttr> e;
TagLibTagAttr att;
while (it.hasNext()) {
e = it.next();
att = e.getValue();
if (!parent.containsAttribute(att.getName()) && att.hasDefaultValue()) {
Attribute attr = new Attribute(tag.getAttributeType() == TagLibTag.ATTRIBUTE_TYPE_DYNAMIC, att.getName(), CastOther.toExpression(data.factory.createLitString(Caster.toString(att.getDefaultValue(), null)), att.getType()), att.getType());
attr.setDefaultAttribute(true);
parent.addAttribute(attr);
}
}
}
boolean hasAttributeCollection = args.contains("attributecollection");
// to less attributes
if (!hasAttributeCollection && min > count)
throw createTemplateException(data.srcCode, "the tag " + tag.getFullName() + " must have at least " + min + " attributes", tag);
// too much attributes
if (!hasAttributeCollection && max > 0 && max < count)
throw createTemplateException(data.srcCode, "the tag " + tag.getFullName() + " can have a maximum of " + max + " attributes", tag);
// not defined attributes
if (type == TagLibTag.ATTRIBUTE_TYPE_FIXED || type == TagLibTag.ATTRIBUTE_TYPE_MIXED) {
// Map<String, TagLibTagAttr> hash = tag.getAttributes();
Iterator<TagLibTagAttr> it = tag.getAttributes().values().iterator();
while (it.hasNext()) {
TagLibTagAttr att = it.next();
if (att.isRequired() && !contains(args, att) && att.getDefaultValue() == null) {
if (!hasAttributeCollection)
throw createTemplateException(data.srcCode, "attribute " + att.getName() + " is required for tag " + tag.getFullName(), tag);
parent.addMissingAttribute(att);
}
}
}
} catch (TemplateException te) {
data.srcCode.setPos(start);
// if the tag supports a non name attribute try this
TagLibTagAttr sa = tag.getSingleAttr();
if (sa != null)
attrNoName(parent, tag, data, sa);
else
throw te;
}
} else // tag without attributes name
{
attrNoName(parent, tag, data, null);
}
}
use of lucee.transformer.library.tag.TagLibTagAttr in project Lucee by lucee.
the class AbstrCFMLScriptTransformer method _paramStatement.
private Tag _paramStatement(ExprData data, Body parent) throws TemplateException {
if (!data.srcCode.forwardIfCurrent("param "))
return null;
Position line = data.srcCode.getPosition();
TagLibTag tlt = CFMLTransformer.getTLT(data.srcCode, "param", data.config.getIdentification());
TagParam param = new TagParam(data.factory, line, null);
// type
boolean hasType = false;
boolean hasName = false;
int pos = data.srcCode.getPos();
// first 2 arguments can be type/name directly
String tmp = variableDec(data, true);
do {
if (!StringUtil.isEmpty(tmp)) {
TagLibTagAttr attr = tlt.getAttribute(tmp.toLowerCase(), true);
// name is not a defined attribute
if (attr == null) {
comments(data);
// it could be a name followed by default value
if (data.srcCode.forwardIfCurrent('=')) {
comments(data);
Expression v = attributeValue(data, true);
param.addAttribute(new Attribute(false, "name", data.factory.createLitString(tmp), "string"));
param.addAttribute(new Attribute(false, "default", v, "string"));
hasName = true;
// if we had a value this was already name
break;
}
// can be type or name
int pos2 = data.srcCode.getPos();
// first could be type, followed by name
comments(data);
String tmp2 = variableDec(data, true);
if (!StringUtil.isEmpty(tmp2)) {
attr = tlt.getAttribute(tmp2.toLowerCase(), true);
if (attr == null) {
param.addAttribute(new Attribute(false, "name", data.factory.createLitString(tmp2), "string"));
param.addAttribute(new Attribute(false, "type", data.factory.createLitString(tmp), "string"));
if (data.srcCode.forwardIfCurrent('=')) {
Expression v = attributeValue(data, true);
param.addAttribute(new Attribute(false, "default", v, "string"));
}
hasName = true;
hasType = true;
break;
}
}
param.addAttribute(new Attribute(false, "name", data.factory.createLitString(tmp), "string"));
data.srcCode.setPos(pos2);
hasName = true;
} else
data.srcCode.setPos(pos);
} else
data.srcCode.setPos(pos);
} while (false);
// folgend wird tlt extra nicht uebergeben, sonst findet pruefung statt
Attribute[] attrs = attributes(param, tlt, data, SEMI, data.factory.NULL(), Boolean.TRUE, "name", true, ',', false);
checkSemiColonLineFeed(data, true, true, true);
param.setTagLibTag(tlt);
param.setScriptBase(true);
Attribute attr;
// first fill all regular attribute -> name="value"
boolean hasDynamic = false;
for (int i = attrs.length - 1; i >= 0; i--) {
attr = attrs[i];
if (!attr.getValue().equals(data.factory.NULL())) {
if (attr.getName().equalsIgnoreCase("name")) {
hasName = true;
param.addAttribute(attr);
} else if (attr.getName().equalsIgnoreCase("type")) {
hasType = true;
param.addAttribute(attr);
} else if (attr.isDynamicType()) {
hasName = true;
if (hasDynamic)
throw attrNotSupported(data.srcCode, tlt, attr.getName());
hasDynamic = true;
param.addAttribute(new Attribute(false, "name", data.factory.createLitString(attr.getName()), "string"));
param.addAttribute(new Attribute(false, "default", attr.getValue(), "any"));
} else
param.addAttribute(attr);
}
}
// now fill name named attributes -> attr1 attr2
String first = null, second = null;
for (int i = 0; i < attrs.length; i++) {
attr = attrs[i];
if (attr.getValue().equals(data.factory.NULL())) {
// type
if (first == null && (!hasName || !hasType)) {
first = attr.getName();
} else // name
if (second == null && !hasName && !hasType) {
second = attr.getName();
} else // attr with no value
{
attr = new Attribute(true, attr.getName(), data.factory.EMPTY(), "string");
param.addAttribute(attr);
}
}
}
if (first != null) {
if (second != null) {
hasName = true;
hasType = true;
if (hasDynamic)
throw attrNotSupported(data.srcCode, tlt, first);
hasDynamic = true;
param.addAttribute(new Attribute(false, "name", data.factory.createLitString(second), "string"));
param.addAttribute(new Attribute(false, "type", data.factory.createLitString(first), "string"));
} else {
param.addAttribute(new Attribute(false, hasName ? "type" : "name", data.factory.createLitString(first), "string"));
hasName = true;
}
}
if (!hasName)
throw new TemplateException(data.srcCode, "missing name declaration for param");
param.setEnd(data.srcCode.getPosition());
return param;
}
use of lucee.transformer.library.tag.TagLibTagAttr in project Lucee by lucee.
the class AbstrCFMLScriptTransformer method attributes.
private final Attribute[] attributes(Tag tag, TagLibTag tlt, ExprData data, EndCondition endCond, Expression defaultValue, Object oAllowExpression, String ignoreAttrReqFor, boolean allowTwiceAttr, char attributeSeparator, boolean allowColonAsNameValueSeparator) throws TemplateException {
ArrayList<Attribute> attrs = new ArrayList<Attribute>();
ArrayList<String> ids = new ArrayList<String>();
while (data.srcCode.isValidIndex()) {
data.srcCode.removeSpace();
// if no more attributes break
if (endCond.isEnd(data))
break;
Attribute attr = attribute(tlt, data, ids, defaultValue, oAllowExpression, allowTwiceAttr, allowColonAsNameValueSeparator);
attrs.add(attr);
// seperator
if (attributeSeparator > 0) {
data.srcCode.removeSpace();
data.srcCode.forwardIfCurrent(attributeSeparator);
}
}
// not defined attributes
if (tlt != null) {
boolean hasAttributeCollection = false;
Iterator<Attribute> iii = attrs.iterator();
while (iii.hasNext()) {
if ("attributecollection".equalsIgnoreCase(iii.next().getName())) {
hasAttributeCollection = true;
break;
}
}
int type = tlt.getAttributeType();
if (type == TagLibTag.ATTRIBUTE_TYPE_FIXED || type == TagLibTag.ATTRIBUTE_TYPE_MIXED) {
Map<String, TagLibTagAttr> hash = tlt.getAttributes();
Iterator<Entry<String, TagLibTagAttr>> it = hash.entrySet().iterator();
Entry<String, TagLibTagAttr> e;
while (it.hasNext()) {
e = it.next();
TagLibTagAttr att = e.getValue();
if (att.isRequired() && !contains(attrs, att) && att.getDefaultValue() == null && !att.getName().equals(ignoreAttrReqFor)) {
if (!hasAttributeCollection)
throw new TemplateException(data.srcCode, "attribute " + att.getName() + " is required for statement " + tlt.getName());
if (tag != null)
tag.addMissingAttribute(att);
}
}
}
}
return attrs.toArray(new Attribute[attrs.size()]);
}
Aggregations