001    package railo.transformer.cfml.evaluator.impl;
002    
003    import railo.commons.lang.StringUtil;
004    import railo.transformer.bytecode.cast.Cast;
005    import railo.transformer.bytecode.cast.CastString;
006    import railo.transformer.bytecode.expression.Expression;
007    import railo.transformer.bytecode.expression.var.Variable;
008    import railo.transformer.bytecode.expression.var.VariableString;
009    import railo.transformer.bytecode.literal.LitString;
010    import railo.transformer.bytecode.statement.tag.Attribute;
011    import railo.transformer.bytecode.statement.tag.Tag;
012    import railo.transformer.bytecode.statement.tag.TagBreak;
013    import railo.transformer.bytecode.util.ASMUtil;
014    import railo.transformer.cfml.evaluator.EvaluatorException;
015    import railo.transformer.cfml.evaluator.EvaluatorSupport;
016    import railo.transformer.library.tag.TagLibTag;
017    
018    
019    
020    /**
021     * Prueft den Kontext des Tag break.
022     * Das Tag <code>break</code> darf nur innerhalb des Tag <code>loop, while, foreach</code> liegen.
023     */
024    public final class Break extends EvaluatorSupport {
025    
026    
027            @Override
028            public void evaluate(Tag tag,TagLibTag libTag) throws EvaluatorException { 
029                    String ns=libTag.getTagLib().getNameSpaceAndSeparator();
030                    String loopName=ns+"loop";
031                    String whileName=ns+"while";
032                    
033    
034                    // label
035                    String label=null;
036                    
037                    Attribute attrLabel = tag.getAttribute("label");
038                    if(attrLabel!=null){
039                            TagBreak tb=(TagBreak) tag;
040                            label=variableToString(tag,attrLabel,null);
041                            if(label!=null){
042                                    tb.setLabel(label=label.trim());
043                                    tag.removeAttribute("label");
044                            }
045                            
046                            else if(ASMUtil.isLiteralAttribute(tag, attrLabel, ASMUtil.TYPE_STRING, false, true)) {
047                                    LitString ls=(LitString) CastString.toExprString(tag.getAttribute("label").getValue());
048                                    label = ls.getString();
049                                    if(!StringUtil.isEmpty(label,true)) {
050                                            tb.setLabel(label=label.trim());
051                                            tag.removeAttribute("label");
052                                    }
053                                    else label=null;
054                            }
055                    }
056                    
057                    if(!ASMUtil.hasAncestorBreakFCStatement(tag,label)) {
058                            if(StringUtil.isEmpty(label))
059                                    throw new EvaluatorException("Wrong Context, tag "+libTag.getFullName()+" must be inside a "+loopName+" or "+whileName+" tag");
060                            throw new EvaluatorException("Wrong Context, tag "+libTag.getFullName()+" must be inside a "+loopName+" or "+whileName+" tag with the label ["+label+"]");
061                            
062                    }
063    
064            }
065    
066            static String variableToString(Tag tag, Attribute attrLabel, String defaultValue) {
067                    Expression value = attrLabel.getValue();
068                    while(value instanceof Cast) value=((Cast)value).getExpr();
069                    if(value instanceof Variable) {
070                            Variable var=(Variable)value;
071                            try {
072                                    return VariableString.variableToString(var, true);
073                            } catch (Throwable t) {}
074                    }
075                    return defaultValue;
076            }
077    
078    }