1 19 20 package org.apache.cayenne.access.jdbc; 21 22 import java.io.StringReader ; 23 import java.io.StringWriter ; 24 import java.util.ArrayList ; 25 import java.util.HashMap ; 26 import java.util.List ; 27 import java.util.Map ; 28 29 import org.apache.cayenne.CayenneRuntimeException; 30 import org.apache.velocity.VelocityContext; 31 import org.apache.velocity.context.InternalContextAdapterImpl; 32 import org.apache.velocity.runtime.RuntimeConstants; 33 import org.apache.velocity.runtime.RuntimeInstance; 34 import org.apache.velocity.runtime.log.NullLogSystem; 35 import org.apache.velocity.runtime.parser.ParseException; 36 import org.apache.velocity.runtime.parser.node.SimpleNode; 37 38 45 class SQLTemplateProcessor { 46 47 private static RuntimeInstance sharedRuntime; 48 49 static final String BINDINGS_LIST_KEY = "bindings"; 50 static final String RESULT_COLUMNS_LIST_KEY = "resultColumns"; 51 static final String HELPER_KEY = "helper"; 52 53 private static final SQLTemplateRenderingUtils sharedUtils = new SQLTemplateRenderingUtils(); 54 55 RuntimeInstance velocityRuntime; 56 SQLTemplateRenderingUtils renderingUtils; 57 58 static { 59 initVelocityRuntime(); 60 } 61 62 private static void initVelocityRuntime() { 63 sharedRuntime = new RuntimeInstance(); 65 66 sharedRuntime.addProperty( 68 RuntimeConstants.RUNTIME_LOG_LOGSYSTEM, 69 new NullLogSystem()); 70 71 sharedRuntime.addProperty( 72 RuntimeConstants.RESOURCE_MANAGER_CLASS, 73 SQLTemplateResourceManager.class.getName()); 74 sharedRuntime.addProperty("userdirective", BindDirective.class.getName()); 75 sharedRuntime.addProperty("userdirective", BindEqualDirective.class.getName()); 76 sharedRuntime.addProperty("userdirective", BindNotEqualDirective.class.getName()); 77 sharedRuntime.addProperty("userdirective", BindObjectEqualDirective.class.getName()); 78 sharedRuntime.addProperty("userdirective", BindObjectNotEqualDirective.class.getName()); 79 sharedRuntime.addProperty("userdirective", ResultDirective.class.getName()); 80 sharedRuntime.addProperty("userdirective", ChainDirective.class.getName()); 81 sharedRuntime.addProperty("userdirective", ChunkDirective.class.getName()); 82 try { 83 sharedRuntime.init(); 84 } 85 catch (Exception ex) { 86 throw new CayenneRuntimeException( 87 "Error setting up Velocity RuntimeInstance.", 88 ex); 89 } 90 } 91 92 SQLTemplateProcessor() { 93 this.velocityRuntime = sharedRuntime; 94 this.renderingUtils = sharedUtils; 95 } 96 97 SQLTemplateProcessor(RuntimeInstance velocityRuntime, 98 SQLTemplateRenderingUtils renderingUtils) { 99 this.velocityRuntime = velocityRuntime; 100 this.renderingUtils = renderingUtils; 101 } 102 103 109 SQLStatement processTemplate(String template, Map parameters) throws Exception { 110 Map internalParameters = (parameters != null && !parameters.isEmpty()) 112 ? new HashMap (parameters) 113 : new HashMap (3); 114 115 List bindings = new ArrayList (); 116 List results = new ArrayList (); 117 internalParameters.put(BINDINGS_LIST_KEY, bindings); 118 internalParameters.put(RESULT_COLUMNS_LIST_KEY, results); 119 internalParameters.put(HELPER_KEY, renderingUtils); 120 121 String sql = buildStatement( 122 new VelocityContext(internalParameters), 123 template, 124 parameters); 125 126 ParameterBinding[] bindingsArray = new ParameterBinding[bindings.size()]; 127 bindings.toArray(bindingsArray); 128 129 ColumnDescriptor[] resultsArray = new ColumnDescriptor[results.size()]; 130 results.toArray(resultsArray); 131 132 return new SQLStatement(sql, resultsArray, bindingsArray); 133 } 134 135 String buildStatement(VelocityContext context, String template, Map parameters) 136 throws Exception { 137 141 StringWriter out = new StringWriter (template.length()); 142 SimpleNode nodeTree = null; 143 144 try { 145 nodeTree = velocityRuntime.parse(new StringReader (template), template); 146 } 147 catch (ParseException pex) { 148 throw new CayenneRuntimeException("Error parsing template '" 149 + template 150 + "' : " 151 + pex.getMessage()); 152 } 153 154 if (nodeTree == null) { 155 throw new CayenneRuntimeException("Error parsing template " + template); 156 } 157 158 InternalContextAdapterImpl ica = new InternalContextAdapterImpl(context); 160 ica.pushCurrentTemplateName(template); 161 162 try { 163 nodeTree.init(ica, velocityRuntime); 164 nodeTree.render(ica, out); 165 return out.toString(); 166 } 167 finally { 168 ica.popCurrentTemplateName(); 169 } 170 } 171 } 172 | Popular Tags |