| 1 52 53 package com.go.teaservlet.util; 54 55 import java.io.IOException ; 56 import java.io.InputStream ; 57 import java.io.File ; 58 import java.io.BufferedInputStream ; 59 import java.io.Reader ; 60 import java.io.InputStreamReader ; 61 import java.io.OutputStream ; 62 import java.io.BufferedOutputStream ; 63 import java.io.FileOutputStream ; 64 import java.io.StreamTokenizer ; 65 import java.net.Socket ; 66 import java.util.Collection ; 67 import java.util.Map ; 68 import java.util.TreeMap ; 69 import java.util.Arrays ; 70 import java.util.Vector ; 71 import com.go.trove.util.ClassInjector; 72 import com.go.trove.io.DualOutput; 73 import com.go.tea.compiler.Compiler; 74 import com.go.tea.compiler.CompilationUnit; 75 import com.go.tea.compiler.ErrorListener; 76 import com.go.tea.util.AbstractFileCompiler; 77 78 94 public class RemoteCompiler extends AbstractFileCompiler { 95 96 private static final String TEMPLATE_LOAD_PROTOCOL = "http://"; 97 private String [] mRemoteSourceDirs; 98 private String mRootPackage; 99 private File mRootDestDir; 100 private ClassInjector mInjector; 101 private String mEncoding; 102 private boolean mForce = false; 103 private Map mTemplateMap; 104 105 106 public RemoteCompiler(String [] rootSourceDirs, 107 String rootPackage, 108 File rootDestDir, 109 ClassInjector injector, 110 String encoding) { 111 super(); 112 mRemoteSourceDirs = rootSourceDirs; 113 mRootPackage = rootPackage; 114 mRootDestDir = rootDestDir; 115 mInjector = injector; 116 mEncoding = encoding; 117 118 if (mRootDestDir != null && 119 !mRootDestDir.isDirectory()) { 120 throw new IllegalArgumentException  121 ("Destination is not a directory: " + rootDestDir); 122 } 123 124 mTemplateMap = retrieveTemplateMap(); 125 } 126 127 130 public void setForceCompile(boolean force) { 131 mForce = force; 132 } 133 134 137 public boolean sourceExists(String name) { 138 return mTemplateMap.containsKey(name); 139 } 140 141 public String [] getAllTemplateNames() { 142 return (String [])mTemplateMap.keySet().toArray(new String [0]); 143 } 144 145 149 public String [] compile(String [] names) throws IOException { 150 String [] compiled = super.compile(names); 151 for (int j=0;j<names.length;j++) { 152 syncSources(names[j]); 153 } 154 return compiled; 155 } 156 157 protected CompilationUnit createCompilationUnit(String name) { 158 return new Unit(name,this); 159 } 160 161 165 private void syncSources(String name) { 166 TemplateSourceInfo info = (TemplateSourceInfo)mTemplateMap.get(name); 167 Unit compUnit = (Unit)this.getCompilationUnit(name,null); 168 compUnit.getDestinationFile().setLastModified(info.timestamp); 169 } 170 171 174 private Socket getTemplateServerSocket(String remoteSource) throws IOException { 175 int port = 80; 176 String host = remoteSource.substring(TEMPLATE_LOAD_PROTOCOL.length()); 177 int portIndex = host.indexOf("/"); 178 179 if (portIndex >= 0) { 180 host = host.substring(0,portIndex); 181 } 182 183 portIndex = host.indexOf(":"); 184 if (portIndex >= 0) { 185 try { 186 port = Integer.parseInt(host.substring(portIndex+1)); 187 } 188 catch (NumberFormatException nfe) { 189 System.out.println("Invalid port number specified"); 190 } 191 host = host.substring(0,portIndex); 192 } 193 return new Socket (host,port); 194 } 195 196 199 private byte[] createTemplateServerRequest(String servletPath,String templateName) { 200 String pathInfo = servletPath.substring(servletPath.indexOf("/",TEMPLATE_LOAD_PROTOCOL.length())); 201 if (templateName != null) { 202 pathInfo = pathInfo + templateName; 203 } 204 return ("GET " + pathInfo + " HTTP/1.0\r\n\r\n").getBytes(); 205 } 206 207 211 private Map retrieveTemplateMap() { 212 Map templateMap = new TreeMap (); 213 for (int j=0;j<mRemoteSourceDirs.length;j++) { 214 String remoteSource = mRemoteSourceDirs[j]; 215 if (!remoteSource.endsWith("/")) { 216 remoteSource = remoteSource + "/"; 217 } 218 219 try { 220 Socket tsSock = getTemplateServerSocket(remoteSource); 221 OutputStream out = new BufferedOutputStream ( 222 tsSock.getOutputStream()); 223 Reader rin = new InputStreamReader (new BufferedInputStream ( 224 tsSock.getInputStream())); 225 226 out.write(createTemplateServerRequest(remoteSource,null)); 227 out.flush(); 228 StreamTokenizer st = new StreamTokenizer (rin); 229 st.resetSyntax(); 230 st.wordChars('!','{'); 231 st.wordChars('}','}'); 232 st.whitespaceChars(0,' '); 233 st.parseNumbers(); 234 st.quoteChar('|'); 235 st.eolIsSignificant(true); 236 String templateName = null; 237 int tokenID = 0; 238 while (!((tokenID = st.nextToken()) == StreamTokenizer.TT_EOL 240 && st.nextToken() == StreamTokenizer.TT_EOL) 241 && tokenID != StreamTokenizer.TT_EOF) { 242 } 243 while ((tokenID = st.nextToken()) != StreamTokenizer.TT_EOF) { 244 if (tokenID == '|' || tokenID == StreamTokenizer.TT_WORD) { 245 246 templateName = st.sval; 247 } 248 else if (tokenID == StreamTokenizer.TT_NUMBER 249 && templateName != null) { 250 templateName = templateName.substring(1); 251 templateMap.put(templateName.replace('/','.'), 253 new TemplateSourceInfo( 254 templateName, 255 remoteSource, 256 (long)st.nval)); 257 templateName = null; 258 } 259 } 260 out.close(); 261 rin.close(); 262 } 263 catch (IOException ioe) { 264 ioe.printStackTrace(); 265 } 266 } 267 return templateMap; 269 } 270 271 274 private class TemplateSourceInfo { 275 public String name; 276 public String server; 277 public long timestamp; 278 279 TemplateSourceInfo(String name,String server,long timestamp) { 280 this.name = name; 281 this.server = server; 282 this.timestamp = timestamp; 283 } 284 } 285 286 public class Unit extends CompilationUnit { 287 288 private String mSourceFilePath; 289 private File mDestDir; 290 private File mDestFile; 291 292 Unit(String name, Compiler compiler) { 293 super(name,compiler); 294 mSourceFilePath = name; 295 String slashPath = mSourceFilePath.replace('.',File.separatorChar); 296 if (slashPath.lastIndexOf(File.separatorChar) >= 0) { 297 mDestDir = new File  298 (mRootDestDir, 299 slashPath.substring(0,slashPath.lastIndexOf(File.separatorChar))); 300 } 301 else { 302 mDestDir = mRootDestDir; 303 } 304 mDestDir.mkdirs(); 305 mDestFile = new File  306 (mDestDir, 307 slashPath.substring(slashPath.lastIndexOf(File.separatorChar) + 1) + ".class"); 308 319 } 320 321 public String getTargetPackage() { 322 return mRootPackage; 323 } 324 325 public String getSourceFileName() { 326 return mSourceFilePath.substring 327 (mSourceFilePath.lastIndexOf('.') + 1) + ".tea"; 328 } 329 330 331 public Reader getReader() throws IOException { 332 Reader reader = null; 333 InputStream in = getTemplateSource(mSourceFilePath); 334 if (mEncoding == null) { 335 reader = new InputStreamReader (in); 336 } 337 else { 338 reader = new InputStreamReader (in, mEncoding); 339 } 340 341 while(!(reader.read() == '\n' && reader.read() == '\r')) {} 342 reader.read(); 343 return reader; 344 } 345 346 public boolean shouldCompile() { 347 if (!mForce && 348 mDestFile != null && 349 mDestFile.exists() && 350 mDestFile.lastModified() >= 351 ((TemplateSourceInfo)mTemplateMap 352 .get(mSourceFilePath)).timestamp) { 353 354 return false; 355 } 356 return true; 357 } 358 359 360 363 public File getDestinationFile() { 364 return mDestFile; 365 } 366 367 public OutputStream getOutputStream() throws IOException { 368 OutputStream out1 = null; 369 OutputStream out2 = null; 370 371 if (mDestDir != null) { 372 if (!mDestDir.exists()) { 373 mDestDir.mkdirs(); 374 } 375 376 out1 = new FileOutputStream (mDestFile); 377 } 378 379 if (mInjector != null) { 380 String className = getName(); 381 String pack = getTargetPackage(); 382 if (pack != null && pack.length() > 0) { 383 className = pack + '.' + className; 384 } 385 out2 = mInjector.getStream(className); 386 } 387 388 OutputStream out; 389 390 if (out1 != null) { 391 if (out2 != null) { 392 out = new DualOutput(out1, out2); 393 } 394 else { 395 out = out1; 396 } 397 } 398 else if (out2 != null) { 399 out = out2; 400 } 401 else { 402 out = new OutputStream () { 403 public void write(int b) {} 404 public void write(byte[] b, int off, int len) {} 405 }; 406 } 407 408 return new BufferedOutputStream (out); 409 } 410 411 414 private InputStream getTemplateSource(String templateSourceName) 415 throws IOException { 416 TemplateSourceInfo tsInfo = (TemplateSourceInfo)mTemplateMap 417 .get(templateSourceName); 418 Socket sock = getTemplateServerSocket(tsInfo.server); 419 OutputStream out = new BufferedOutputStream ( 420 sock.getOutputStream()); 421 InputStream in = new BufferedInputStream (sock.getInputStream()); 422 423 out.write(createTemplateServerRequest(tsInfo.server,tsInfo.name + ".tea")); 424 out.flush(); 425 return in; 427 } 428 } 429 } 430 | Popular Tags |