📄 recompilingtemplatemanager.java
字号:
@SuppressWarnings("unchecked") private Class<? extends AbstractTemplateProxy> getProxyClass(String p_path) { return getTemplateClass( p_path, StringUtils.templatePathToClassName(p_path)) .asSubclass(AbstractTemplateProxy.class); } private Class<?> getTemplateClass( String p_path, String p_className) { try { try { ensureUpToDate( p_path, new TemplateDescriber(m_templateSource, m_loader)); return m_loader.loadClass(p_className); } catch (ClassNotFoundException e) { if (! m_templateSource.available(p_path)) { throw new UnknownTemplateException(p_path); } else { throw new JamonRuntimeException(e); } } } catch (IOException e) { throw new JamonRuntimeException(e); } } private final TemplateSource m_templateSource; private final String m_workDir; private final ClassLoader m_classLoader; private final JavaCompiler m_javaCompiler; private final WorkDirClassLoader m_loader; private String prefix() { return m_workDir; } private String javaImpl(String p_path) { return prefix() + p_path + "Impl.java"; } private String classImpl(String p_path) { return prefix() + p_path + "Impl.class"; } private String javaIntf(String p_path) { return prefix() + p_path + ".java"; } private synchronized void ensureUpToDate(String p_path, TemplateDescriber p_describer) throws IOException { Collection<String> seen = new HashSet<String>(); Collection<String> outOfDateJavaFiles = new HashSet<String>(); List<String> workQueue = new LinkedList<String>(); workQueue.add(p_path); while (!workQueue.isEmpty()) { String path = workQueue.remove(0); if (TRACE) { trace("processing " + path); } seen.add(path); if (! m_templateSource.available(path)) { if (TRACE) { trace(path + " source not found; assume class exists"); } continue; } boolean intfGenerated = false; long modTime = m_templateSource.lastModified(path); String intfFileName = javaIntf(path); File intfFile = new File(intfFileName); if (intfFile.lastModified() < modTime) { TemplateUnit templateUnit = new Analyzer(path, p_describer).analyze(); String signature = templateUnit.getSignature(); if (isIntfChanged(path, signature, m_classLoader)) { if (isIntfChanged(path, signature, m_loader)) { generateIntf(path, p_describer, templateUnit); outOfDateJavaFiles.add(intfFileName); intfGenerated = true; } } else { intfFile.delete(); deleteClassFilesFor(path); } } File jm = new File(javaImpl(path)); long ts = jm.lastModified(); if (jm.lastModified() < modTime) { m_dependencyCache.put (path, new DependencyEntry(generateImpl(path,p_describer))); ts = System.currentTimeMillis(); } if (new File(classImpl(path)).lastModified() < ts || intfGenerated) { outOfDateJavaFiles.add(javaImpl(path)); } DependencyEntry d = m_dependencyCache.get(path); if (d == null || d.lastUpdated() < modTime) { d = new DependencyEntry(computeDependencies(path,p_describer)); m_dependencyCache.put(path, d); } for (Iterator<String> y = d.getDependencies(); y.hasNext(); /* */) { String dp = y.next(); if (! seen.contains(dp)) { workQueue.add(dp); } } } if (!outOfDateJavaFiles.isEmpty()) { String errors = compile(outOfDateJavaFiles); m_loader.invalidate(); if (errors != null) { throw new TemplateCompilationException(errors); } } } private void deleteClassFilesFor(String p_path) { int i = p_path.lastIndexOf('/'); String templateName = i < 0 ? p_path : p_path.substring(i+1); File dir = new File(new File(m_workDir), StringUtils.templatePathToFileDir(p_path)); String[] files = dir.list(); if (files != null) { for (int j = 0; j < files.length; ++j) { if (StringUtils.isGeneratedClassFilename(templateName, files[j])) { new File(dir, files[j]).delete(); // FIXME: error checking? } } } } private File getWriteableFile(String p_filename) { File file = new File(p_filename); File parent = file.getParentFile(); if (parent != null) { parent.mkdirs(); } return file; } private void generateSource( String p_filename, SourceGenerator p_sourceGenerator) throws IOException { File javaFile = getWriteableFile(p_filename); FileOutputStream out = new FileOutputStream(javaFile); try { p_sourceGenerator.generateSource(out); out.close(); } catch (IOException e) { out.close(); javaFile.delete(); throw e; } } /** * @return dependencies */ private Collection<String> generateImpl(String p_path, TemplateDescriber p_describer) throws IOException { if (TRACE) { trace("generating impl for " + p_path); } TemplateUnit templateUnit = new Analyzer(p_path,p_describer).analyze(); generateSource( javaImpl(p_path), new ImplGenerator(p_describer, templateUnit)); return templateUnit.getTemplateDependencies(); } private void generateIntf(String p_path, TemplateDescriber p_describer, TemplateUnit p_templateUnit) throws IOException { if (TRACE) { trace("generating intf for " + p_path); } generateSource(javaIntf(p_path), new ProxyGenerator(p_describer, p_templateUnit)); } private String getIntfSignatureFromClass(String p_path, ClassLoader p_loader) { if (TRACE) { trace("Looking for signature of " + StringUtils.templatePathToClassName(p_path)); } try { return p_loader .loadClass(StringUtils.templatePathToClassName(p_path)) .getAnnotation(Template.class) .signature(); } catch (ClassNotFoundException e) { return null; } } private boolean isIntfChanged(String p_path, String p_signature, ClassLoader p_loader) { return ! p_signature.equals(getIntfSignatureFromClass(p_path, p_loader)); } private String compile(Collection<String> p_sourceFiles) { if (p_sourceFiles.isEmpty()) { return null; } StringBuilder buf = new StringBuilder(); buf.append("compiling: "); for (Iterator<String> i = p_sourceFiles.iterator(); i.hasNext(); /* */) { buf.append(i.next()); if (i.hasNext()) { buf.append(", "); } } if (TRACE) { trace(buf.toString()); } return m_javaCompiler.compile(p_sourceFiles.toArray(new String [0])); } private Collection<String> computeDependencies( String p_path, TemplateDescriber p_describer) throws IOException { if (TRACE) { trace("computing dependencies for " + p_path); } return new Analyzer(p_path, p_describer) .analyze() .getTemplateDependencies(); } private Map<String, DependencyEntry> m_dependencyCache = new HashMap<String, DependencyEntry>(); private static class DependencyEntry { DependencyEntry(Collection<String> p_dependencies) { m_dependencies = p_dependencies; m_lastUpdated = System.currentTimeMillis(); } Collection<String> m_dependencies; long m_lastUpdated; Iterator<String> getDependencies() { return m_dependencies.iterator(); } long lastUpdated() { return m_lastUpdated; } } private static final boolean TRACE = Boolean.valueOf(System.getProperty (RecompilingTemplateManager.class.getName() + ".trace" )).booleanValue();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -