##### Coverage Report - org.webmacro.directive.SetpropsDirective

Classes in this File | Line Coverage | Branch Coverage | Complexity
SetpropsDirective |
4% | 3/65
0% | 0/18
| 4.0;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 | 2 |
         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 | 2 |
         private static final DirectiveDescriptor myDescr = new DirectiveDescriptor(
71 |  |
                 "setprops", null, myArgs, null);
72 |  |
73 |  |
         public static DirectiveDescriptor getDescriptor ()
74 |  |
         {
75 | 6 |
             return myDescr;
76 |  |
         }
77 |  |
78 |  |
         public SetpropsDirective()
79 | 0 |
         {
80 | 0 |
         }
81 |  |
82 |  |
         public Object build (DirectiveBuilder builder, BuildContext bc)
83 |  |
                 throws BuildException
84 |  |
         {
85 |  |
             try {
86 | 0 |
                 target = (Variable) builder.getArg(PROPS_TARGET, bc);
87 | 0 |
             } catch (ClassCastException e) {
88 | 0 |
                 throw new NotVariableBuildException(myDescr.name, e);
89 | 0 |
             }
90 | 0 |
             _className = (String) builder.getArg(PROPS_CLASSNAME, bc);
91 | 0 |
             if (_className == null)
92 | 0 |
                 _className = DEFAULT_CLASS_NAME;
93 | 0 |
             result = builder.getArg(PROPS_RESULT, bc);
94 | 0 |
             return this;
95 |  |
         }
96 |  |
97 |  |
         public void write (FastWriter out, Context context)
98 |  |
                 throws PropertyException, IOException
99 |  |
         {
100 |  |
101 |  |
             try {
102 | 0 |
                 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 | 0 |
                         Class c = Instantiator.getInstance(context.getBroker())
107 |  |
                                 .classForName(_className);
108 | 0 |
                         Object o = c.newInstance();
109 | 0 |
                         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 | 0 |
                     }
115 |  |
116 |  |
                 }
117 | 0 |
                 String res = (String) ((Macro) result).evaluate(context);
118 | 0 |
                 String[] lines = TextTool.getLines(res);
119 |  |
                 String s;
120 | 0 |
                 String prevLine = "";
121 | 0 |
                 String prefix = "#set $" + target.getVariableName() + ".";
122 | 0 |
                 for (int i = 0; i < lines.length; i++) {
123 | 0 |
                     s = prevLine + lines[i].trim();
124 | 0 |
                     if (s.endsWith("\\")) {
125 |  |
                         // ends with continuation character. Add to next line.
126 | 0 |
                         prevLine = s.substring(0, s.length() - 1);
127 |  |
                     } else {
128 | 0 |
                         prevLine = "";
129 | 0 |
                         setProp(context, s, prefix);
130 |  |
                     }
131 |  |
                 }
132 | 0 |
             } catch (PropertyException e) {
133 | 0 |
                 throw e;
134 | 0 |
             } catch (Exception e) {
135 | 0 |
                 String errorText = "#setprops: Unable to set " + target + " as " + e.getMessage();
136 | 0 |
                 writeWarning(errorText, context, out);
137 | 0 |
             }
138 | 0 |
         }
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 | 0 |
             if (s.length() > 0 && !s.startsWith("#")) {
148 | 0 |
                 for (int j = 0; j < s.length(); j++) {
149 | 0 |
                     char ch = s.charAt(j);
150 | 0 |
                     if (ch == ':' || ch == '=') {
151 | 0 |
                         prop = s.substring(0, j).trim();
152 | 0 |
                         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 | 0 |
                         s = prefix + prop + "=\"" + val + "\"";
158 |  |
                         try {
159 | 0 |
                             stringTemplate = new StringTemplate(context.getBroker(), s);
160 | 0 |
                             stringTemplate.evaluateAsString(context);
161 | 0 |
                         } catch (WebMacroException wme) {
162 |  |
                             // try again without quotes.
163 | 0 |
                             s = prefix + prop + "=" + val;
164 |  |
                             try {
165 | 0 |
                                 stringTemplate = new StringTemplate(context.getBroker(), s);
166 | 0 |
                                 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 | 0 |
                             }
178 | 0 |
                         }
179 | 0 |
                         break;
180 |  |
                     }
181 |  |
                 }
182 |  |
             }
183 |  |
184 | 0 |
         }
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 |  |
     }