Coverage Report - org.webmacro.directive.SetpropsDirective
 
Classes in this File Line Coverage Branch Coverage Complexity
SetpropsDirective
75%
49/65
83%
15/18
4
 
 1  
 /*
 2  
  * Copyright (C) 2005 Semiotek Inc.  All Rights Reserved.
 3  
  *
 4  
  * Redistribution and use in source and binary forms, with or without
 5  
  * modification, are permitted under the terms of either of the following
 6  
  * Open Source licenses:
 7  
  *
 8  
  * The GNU General Public License, version 2, or any later version, as
 9  
  * published by the Free Software Foundation
 10  
  * (http://www.fsf.org/copyleft/gpl.html);
 11  
  *
 12  
  *  or
 13  
  *
 14  
  * The Semiotek Public License (http://webmacro.org/LICENSE.)
 15  
  *
 16  
  * This software is provided "as is", with NO WARRANTY, not even the
 17  
  * implied warranties of fitness to purpose, or merchantability. You
 18  
  * assume all risks and liabilities associated with its use.
 19  
  *
 20  
  * See www.webmacro.org for more information on the WebMacro project.
 21  
  */
 22  
 
 23  
 package org.webmacro.directive;
 24  
 
 25  
 import java.io.IOException;
 26  
 
 27  
 import org.webmacro.Context;
 28  
 import org.webmacro.FastWriter;
 29  
 import org.webmacro.Macro;
 30  
 import org.webmacro.PropertyException;
 31  
 import org.webmacro.TemplateVisitor;
 32  
 import org.webmacro.WebMacroException;
 33  
 import org.webmacro.engine.BuildContext;
 34  
 import org.webmacro.engine.BuildException;
 35  
 import org.webmacro.engine.StringTemplate;
 36  
 import org.webmacro.engine.Variable;
 37  
 import org.webmacro.servlet.TextTool;
 38  
 import org.webmacro.util.Instantiator;
 39  
 
 40  
 /**
 41  
  * Set properties on an object using Java properties file
 42  
  * type syntax.
 43  
  * 
 44  
  * @author Keats Kirsch 
 45  
  */
 46  
 public class SetpropsDirective extends Directive
 47  
 {
 48  
 
 49  
     private static final String DEFAULT_CLASS_NAME = "java.util.Hashtable";
 50  
 
 51  
     private static final int PROPS_TARGET = 1;
 52  
 
 53  
     private static final int PROPS_CLASS = 2;
 54  
 
 55  
     private static final int PROPS_CLASSNAME = 3;
 56  
 
 57  
     private static final int PROPS_RESULT = 4;
 58  
 
 59  
     private Variable target;
 60  
 
 61  
     private Object result;
 62  
 
 63  
     private String _className;
 64  
 
 65  40
     private static final ArgDescriptor[] myArgs = new ArgDescriptor[] {
 66  
             new LValueArg(PROPS_TARGET), new OptionalGroup(3),
 67  
             new KeywordArg(PROPS_CLASS, "class"), new AssignmentArg(),
 68  
             new QuotedStringArg(PROPS_CLASSNAME), new BlockArg(PROPS_RESULT) };
 69  
 
 70  40
     private static final DirectiveDescriptor myDescr = new DirectiveDescriptor(
 71  
             "setprops", null, myArgs, null);
 72  
 
 73  
     public static DirectiveDescriptor getDescriptor ()
 74  
     {
 75  63
         return myDescr;
 76  
     }
 77  
 
 78  
     public SetpropsDirective()
 79  72
     {
 80  72
     }
 81  
 
 82  
     public Object build (DirectiveBuilder builder, BuildContext bc)
 83  
             throws BuildException
 84  
     {
 85  
         try {
 86  72
             target = (Variable) builder.getArg(PROPS_TARGET, bc);
 87  0
         } catch (ClassCastException e) {
 88  0
             throw new NotVariableBuildException(myDescr.name, e);
 89  72
         }
 90  72
         _className = (String) builder.getArg(PROPS_CLASSNAME, bc);
 91  72
         if (_className == null)
 92  25
             _className = DEFAULT_CLASS_NAME;
 93  72
         result = builder.getArg(PROPS_RESULT, bc);
 94  72
         return this;
 95  
     }
 96  
 
 97  
     public void write (FastWriter out, Context context)
 98  
             throws PropertyException, IOException
 99  
     {
 100  
 
 101  
         try {
 102  72
             if (!context.containsKey(target.getName())) {
 103  
                 // target doesn't exist. Must create.
 104  
                 // TODO check for class loading restrictions as per bean directive
 105  
                 try {
 106  10
                     Class c = Instantiator.getInstance(context.getBroker())
 107  
                             .classForName(_className);
 108  9
                     Object o = c.newInstance();
 109  9
                     target.setValue(context, o);
 110  0
                 } catch (RuntimeException re) {
 111  0
                     throw new PropertyException("Failed to create instance of "
 112  
                             + _className + " for the #properties directive. "
 113  
                             + re, re);
 114  9
                 }
 115  
 
 116  
             }
 117  71
             String res = (String) ((Macro) result).evaluate(context);
 118  71
             String[] lines = TextTool.getLines(res);
 119  
             String s;
 120  71
             String prevLine = "";
 121  71
             String prefix = "#set $" + target.getVariableName() + ".";
 122  319
             for (int i = 0; i < lines.length; i++) {
 123  248
                 s = prevLine + lines[i].trim();
 124  248
                 if (s.endsWith("\\")) {
 125  
                     // ends with continuation character. Add to next line.
 126  2
                     prevLine = s.substring(0, s.length() - 1);
 127  
                 } else {
 128  246
                     prevLine = "";
 129  246
                     setProp(context, s, prefix);
 130  
                 }
 131  
             }
 132  0
         } catch (PropertyException e) {
 133  0
             throw e;
 134  1
         } catch (Exception e) {
 135  1
             String errorText = "#setprops: Unable to set " + target + " as " + e.getMessage();
 136  1
             writeWarning(errorText, context, out);
 137  71
         }
 138  71
     }
 139  
 
 140  
     private void setProp (Context context, String s, String prefix)
 141  
             throws PropertyException
 142  
     {
 143  
         String prop;
 144  
         String val;
 145  
         StringTemplate stringTemplate;
 146  
 
 147  246
         if (s.length() > 0 && !s.startsWith("#")) {
 148  1979
             for (int j = 0; j < s.length(); j++) {
 149  1979
                 char ch = s.charAt(j);
 150  1979
                 if (ch == ':' || ch == '=') {
 151  223
                     prop = s.substring(0, j).trim();
 152  223
                     val = s.substring(j + 1).trim();
 153  
                     // convert to WM syntax and evaluate
 154  
                     // if (val.length() > 0)
 155  
                     // {
 156  
                     // try first as a string
 157  223
                     s = prefix + prop + "=\"" + val + "\"";
 158  
                     try {
 159  223
                         stringTemplate = new StringTemplate(context.getBroker(), s);
 160  223
                         stringTemplate.evaluateAsString(context);
 161  4
                     } catch (WebMacroException wme) {
 162  
                         // try again without quotes.
 163  4
                         s = prefix + prop + "=" + val;
 164  
                         try {
 165  4
                             stringTemplate = new StringTemplate(context.getBroker(), s);
 166  4
                             stringTemplate.evaluateAsString(context);
 167  0
                         } catch (WebMacroException wme2) {
 168  0
                             PropertyException pex = new PropertyException(
 169  
                                     "Failed to set property \"" + prop
 170  
                                             + "\" to value \"" + val
 171  
                                             + "\" on variable \""
 172  
                                             + target.getVariableName()
 173  
                                             + "\" of type "
 174  
                                             + target.getClass().getName(), wme2);
 175  0
                             context.getEvaluationExceptionHandler().evaluate(
 176  
                                     this.target, context, pex);
 177  4
                         }
 178  219
                     }
 179  4
                     break;
 180  
                 }
 181  
             }
 182  
         }
 183  
 
 184  246
     }
 185  
 
 186  
     public void accept (TemplateVisitor v)
 187  
     {
 188  0
         v.beginDirective(myDescr.name);
 189  0
         v.visitDirectiveArg("PropertiesClassKeyword", "class");
 190  0
         v.visitDirectiveArg("PropertiesClassName", _className);
 191  0
         v.visitDirectiveArg("PropertiesTarget", target);
 192  0
         v.visitDirectiveArg("PropertiesValue", result);
 193  0
         v.endDirective();
 194  0
     }
 195  
 
 196  
 }