001 /* 002 @license.text@ 003 */ 004 005 package biz.hammurapi.render.dom; 006 007 import java.io.IOException; 008 import java.io.InputStream; 009 import java.io.OutputStream; 010 import java.io.UnsupportedEncodingException; 011 import java.util.HashMap; 012 import java.util.Iterator; 013 import java.util.Map; 014 015 import javax.xml.parsers.DocumentBuilder; 016 import javax.xml.parsers.DocumentBuilderFactory; 017 import javax.xml.parsers.ParserConfigurationException; 018 import javax.xml.transform.Templates; 019 import javax.xml.transform.Transformer; 020 import javax.xml.transform.TransformerConfigurationException; 021 import javax.xml.transform.TransformerException; 022 import javax.xml.transform.TransformerFactory; 023 import javax.xml.transform.dom.DOMSource; 024 import javax.xml.transform.stream.StreamResult; 025 import javax.xml.transform.stream.StreamSource; 026 027 import org.w3c.dom.Element; 028 029 import biz.hammurapi.config.Parameterizable; 030 import biz.hammurapi.render.RenderRequest; 031 import biz.hammurapi.render.RenderingException; 032 033 034 /** 035 * 036 * @author Pavel Vlasov 037 * @version $Revision: 1.5 $ 038 */ 039 public abstract class AbstractRenderer implements DomRenderer, Parameterizable { 040 private static class StyleKey { 041 Class clazz; 042 String profile; 043 044 public StyleKey(Class clazz, String profile) { 045 super(); 046 this.clazz = clazz; 047 this.profile = profile; 048 } 049 050 public boolean equals(Object obj) { 051 if (obj==this) { 052 return true; 053 } else if (obj instanceof StyleKey) { 054 StyleKey otherKey=(StyleKey) obj; 055 if (clazz.equals(otherKey.clazz)) { 056 if (profile==null) { 057 return otherKey.profile==null; 058 } else if (otherKey.profile==null) { 059 return false; 060 } else { 061 return profile.equals(otherKey.profile); 062 } 063 } 064 return false; 065 } else { 066 return super.equals(obj); 067 } 068 } 069 070 public int hashCode() { 071 int ret=clazz.hashCode(); 072 if (profile!=null) { 073 ret^=profile.hashCode(); 074 } 075 return ret; 076 } 077 } 078 079 private static Map styleMap=new HashMap(); 080 081 protected RenderRequest request; 082 protected String profile; 083 public static final String PROFILE_SEPARATOR="!"; 084 085 protected AbstractRenderer(RenderRequest request) { 086 this.request=request; 087 } 088 089 protected AbstractRenderer(RenderRequest request, String profile) { 090 this.request=request; 091 this.profile=profile; 092 } 093 094 /** 095 * Searches for class name first, then for all interfaces and then for 096 * superclass. 097 * @param clazz 098 * @return 099 * @throws TransformerConfigurationException 100 */ 101 public synchronized Transformer getEmbeddedStyle(Class clazz) throws TransformerConfigurationException { 102 StyleKey key=new StyleKey(clazz, profile); 103 Templates templates=(Templates) styleMap.get(key); 104 if (templates==null) { 105 String transletClass=clazz.getName()+StyleCompiler.POSTFIX; 106 if (profile!=null) { 107 transletClass+=StyleCompiler.TRANSLET_PROFILE_SEPARATOR+profile; 108 } 109 110 // try { 111 // getClass().getClassLoader().loadClass(transletClass); 112 // int idx=transletClass.lastIndexOf('.'); 113 // TransformerFactory tf=new TransformerFactoryImpl(); 114 // tf.setAttribute("use-classpath", Boolean.TRUE); 115 // if (idx!=-1) { 116 // tf.setAttribute("package-name", transletClass.substring(0, idx)); 117 // } 118 // templates=tf.newTemplates(new StreamSource(idx==-1 ? transletClass : transletClass.substring(idx+1))); 119 // styleMap.put(key, templates); 120 // return templates.newTransformer(); 121 // } catch (ClassNotFoundException e) { 122 String resourceName=clazz.getName().replace('.','/')+(profile==null ? "" : PROFILE_SEPARATOR+profile)+".xsl"; 123 InputStream rets=getClass().getClassLoader().getResourceAsStream(resourceName); 124 if (rets!=null) { 125 TransformerFactory tf=TransformerFactory.newInstance(); 126 templates=tf.newTemplates(new StreamSource(rets)); 127 styleMap.put(key, templates); 128 return templates.newTransformer(); 129 } 130 // } 131 132 Class[] interfaces = clazz.getInterfaces(); 133 for (int i=0; i<interfaces.length; i++) { 134 Transformer rett=getEmbeddedStyle(interfaces[i]); 135 if (rett!=null) { 136 return rett; 137 } 138 } 139 140 if (clazz.getSuperclass()==null) { 141 styleMap.put(key, null); 142 return null; 143 } 144 return getEmbeddedStyle(clazz.getSuperclass()); 145 } 146 return templates.newTransformer(); 147 } 148 149 public RenderRequest render(OutputStream out) throws RenderingException { 150 return render(null, out); 151 } 152 153 public RenderRequest render(InputStream style, OutputStream out) throws RenderingException { 154 try { 155 Transformer transformer=null; 156 157 if (style==null && useEmbeddedStyle) { 158 transformer=getEmbeddedStyle(request.getRenderee().getClass()); 159 } 160 161 if (transformer==null) { 162 TransformerFactory tFactory = TransformerFactory.newInstance(); 163 transformer = 164 style==null ? 165 tFactory.newTransformer() : 166 tFactory.newTransformer(new StreamSource(style)); 167 } 168 169 Iterator pit=params.entrySet().iterator(); 170 while (pit.hasNext()) { 171 Map.Entry entry=(Map.Entry) pit.next(); 172 transformer.setParameter((String) entry.getKey(), entry.getValue()); 173 } 174 175 DocumentBuilder builder=null; 176 177 if (request.getDocument()==null) { 178 DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance(); 179 builder=factory.newDocumentBuilder(); 180 request.setDocument(builder.newDocument()); 181 request.getDocument().appendChild(render(request.getDocument())); 182 } 183 184 DOMSource domSource = new DOMSource(request.getDocument()); 185 transformer.transform(domSource, new StreamResult(out)); 186 out.close(); 187 return request; 188 } catch (TransformerConfigurationException e) { 189 throw new RenderingException(e.toString(), e); 190 } catch (ParserConfigurationException e) { 191 throw new RenderingException(e.toString(), e); 192 } catch (TransformerException e) { 193 throw new RenderingException(e.toString(), e); 194 } catch (UnsupportedEncodingException e) { 195 throw new RenderingException(e.toString(), e); 196 } catch (IOException e) { 197 throw new RenderingException(e.toString(), e); 198 } 199 } 200 201 protected boolean useEmbeddedStyle=true; 202 203 public void setEmbeddedStyle(boolean useEmbeddedStyle) { 204 this.useEmbeddedStyle=useEmbeddedStyle; 205 } 206 207 protected Map params=new HashMap(); 208 209 public boolean setParameter(String name, Object value) { 210 params.put(name, value); 211 return true; 212 } 213 214 /** 215 * Creates and add element with text if text!=null && name!=null 216 * @param name 217 * @param text 218 * @param owner 219 * @return 220 */ 221 public static void appendTextElement(String name, String text, Element owner) { 222 if (name!=null && text!=null) { 223 Element e=owner.getOwnerDocument().createElement(name); 224 owner.appendChild(e); 225 e.appendChild(owner.getOwnerDocument().createTextNode(text)); 226 } 227 } 228 }