1 9 10 package com.opensymphony.module.sitemesh.factory; 11 12 import com.opensymphony.module.sitemesh.Config; 13 import com.opensymphony.module.sitemesh.DecoratorMapper; 14 import com.opensymphony.module.sitemesh.PageParser; 15 16 import org.w3c.dom.Document ; 17 import org.w3c.dom.Element ; 18 import org.w3c.dom.NodeList ; 19 import org.w3c.dom.Text ; 20 import org.xml.sax.SAXException ; 21 22 import javax.xml.parsers.DocumentBuilder ; 23 import javax.xml.parsers.DocumentBuilderFactory ; 24 import javax.xml.parsers.ParserConfigurationException ; 25 import java.io.File ; 26 import java.io.IOException ; 27 import java.io.InputStream ; 28 import java.util.*; 29 30 38 public class DefaultFactory extends BaseFactory { 39 String configFileName = "/WEB-INF/sitemesh.xml"; 40 File configFile; 41 long configLastModified; 42 Map configProps = new HashMap(); 43 44 String excludesFileName; 45 File excludesFile; 46 47 public DefaultFactory(Config config) { 48 super(config); 49 50 String configFilePath = config.getServletContext().getRealPath(configFileName); 52 53 if (configFilePath != null) { configFile = new File (configFilePath); 55 } 56 57 loadConfig(); 58 } 59 60 61 public DecoratorMapper getDecoratorMapper() { 62 refresh(); 63 return super.getDecoratorMapper(); 64 } 65 66 67 public PageParser getPageParser(String contentType) { 68 refresh(); 69 return super.getPageParser(contentType); 70 } 71 72 73 public boolean shouldParsePage(String contentType) { 74 refresh(); 75 return super.shouldParsePage(contentType); 76 } 77 78 83 public boolean isPathExcluded(String path) { 84 refresh(); 85 return super.isPathExcluded(path); 86 } 87 88 89 private synchronized void loadConfig() { 90 try { 91 Element root = loadSitemeshXML(); 93 94 NodeList sections = root.getChildNodes(); 95 for (int i = 0; i < sections.getLength(); i++) { 97 if (sections.item(i) instanceof Element ) { 98 Element curr = (Element )sections.item(i); 99 NodeList children = curr.getChildNodes(); 100 101 if ("property".equalsIgnoreCase(curr.getTagName())) { 102 String name = curr.getAttribute("name"); 103 String value = curr.getAttribute("value"); 104 if (!"".equals(name) && !"".equals(value)) { 105 configProps.put("${" + name + "}", value); 106 } 107 } 108 else if ("page-parsers".equalsIgnoreCase(curr.getTagName())) { 109 loadPageParsers(children); 111 } 112 else if ("decorator-mappers".equalsIgnoreCase(curr.getTagName())) { 113 loadDecoratorMappers(children); 115 } 116 else if ("excludes".equalsIgnoreCase(curr.getTagName())) { 117 String fileName = replaceProperties(curr.getAttribute("file")); 119 if (!"".equals(fileName)) { 120 excludesFileName = fileName; 121 loadExcludes(); 122 } 123 } 124 } 125 } 126 } 127 catch (ParserConfigurationException e) { 128 report("Could not get XML parser", e); 129 } 130 catch (IOException e) { 131 report("Could not read config file : " + configFileName, e); 132 } 133 catch (SAXException e) { 134 report("Could not parse config file : " + configFileName, e); 135 } 136 } 137 138 private Element loadSitemeshXML() 139 throws ParserConfigurationException , IOException , SAXException 140 { 141 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 142 DocumentBuilder builder = factory.newDocumentBuilder(); 143 144 InputStream is = null; 145 146 if (configFile == null) { 147 is = config.getServletContext().getResourceAsStream(configFileName); 148 } 149 else if (configFile.exists() && configFile.canRead()) { 150 is = configFile.toURL().openStream(); 151 } 152 153 if (is == null){ is = getClass().getClassLoader().getResourceAsStream("com/opensymphony/module/sitemesh/factory/sitemesh-default.xml"); 155 } 156 157 if (is == null){ is = Thread.currentThread().getContextClassLoader().getResourceAsStream("com/opensymphony/module/sitemesh/factory/sitemesh-default.xml"); 159 } 160 161 if (is == null){ 162 throw new IllegalStateException ("Cannot load default configuration from jar"); 163 } 164 165 if (configFile != null) configLastModified = configFile.lastModified(); 166 167 Document doc = builder.parse(is); 168 Element root = doc.getDocumentElement(); 169 if (!"sitemesh".equalsIgnoreCase(root.getTagName())) { 171 report("Root element of sitemesh configuration file not <sitemesh>", null); 172 } 173 return root; 174 } 175 176 private void loadExcludes() 177 throws ParserConfigurationException , IOException , SAXException 178 { 179 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 180 DocumentBuilder builder = factory.newDocumentBuilder(); 181 182 InputStream is = null; 183 184 if (excludesFile == null) { 185 is = config.getServletContext().getResourceAsStream(excludesFileName); 186 } 187 else if (excludesFile.exists() && excludesFile.canRead()) { 188 is = excludesFile.toURL().openStream(); 189 } 190 191 if (is == null){ 192 throw new IllegalStateException ("Cannot load excludes configuration file from jar"); 193 } 194 195 Document document = builder.parse(is); 196 Element root = document.getDocumentElement(); 197 NodeList sections = root.getChildNodes(); 198 199 for (int i = 0; i < sections.getLength(); i++) { 201 if (sections.item(i) instanceof Element ) { 202 Element curr = (Element )sections.item(i); 203 if ("excludes".equalsIgnoreCase(curr.getTagName())) { 204 loadExcludeUrls(curr.getChildNodes()); 205 } 206 } 207 } 208 } 209 210 211 private void loadPageParsers(NodeList nodes) { 212 clearParserMappings(); 213 for (int i = 0; i < nodes.getLength(); i++) { 214 if (nodes.item(i) instanceof Element ) { 215 Element curr = (Element )nodes.item(i); 216 217 if ("parser".equalsIgnoreCase(curr.getTagName())) { 218 String className = curr.getAttribute("class"); 219 String contentType = curr.getAttribute("content-type"); 220 mapParser(contentType, className); 221 } 222 } 223 } 224 } 225 226 private void loadDecoratorMappers(NodeList nodes) { 227 clearDecoratorMappers(); 228 Properties emptyProps = new Properties(); 229 230 pushDecoratorMapper("com.opensymphony.module.sitemesh.mapper.NullDecoratorMapper", emptyProps); 231 232 for (int i = nodes.getLength() - 1; i > 0; i--) { 234 if (nodes.item(i) instanceof Element ) { 235 Element curr = (Element )nodes.item(i); 236 if ("mapper".equalsIgnoreCase(curr.getTagName())) { 237 String className = curr.getAttribute("class"); 238 Properties props = new Properties(); 239 NodeList children = curr.getChildNodes(); 241 for (int j = 0; j < children.getLength(); j++) { 242 if (children.item(j) instanceof Element ) { 243 Element currC = (Element )children.item(j); 244 if ("param".equalsIgnoreCase(currC.getTagName())) { 245 String value = currC.getAttribute("value"); 246 props.put(currC.getAttribute("name"), replaceProperties(value)); 247 } 248 } 249 } 250 pushDecoratorMapper(className, props); 252 } 253 } 254 } 255 256 pushDecoratorMapper("com.opensymphony.module.sitemesh.mapper.InlineDecoratorMapper", emptyProps); 257 } 258 259 262 private void loadExcludeUrls(NodeList nodes) { 263 clearExcludeUrls(); 264 for (int i = 0; i < nodes.getLength(); i++) { 265 if (nodes.item(i) instanceof Element ) { 266 Element p = (Element ) nodes.item(i); 267 if ("pattern".equalsIgnoreCase(p.getTagName()) || "url-pattern".equalsIgnoreCase(p.getTagName())) { 268 Text patternText = (Text ) p.getFirstChild(); 269 if (patternText != null) { 270 String pattern = patternText.getData().trim(); 271 if (pattern != null) { 272 addExcludeUrl(pattern); 273 } 274 } 275 } 276 } 277 } 278 } 279 280 281 private void refresh() { 282 if (configFile != null && configLastModified != configFile.lastModified()) loadConfig(); 283 } 284 285 293 private String replaceProperties(String str) { 294 Set props = configProps.entrySet(); 295 for (Iterator it = props.iterator(); it.hasNext();) 296 { 297 Map.Entry entry = (Map.Entry) it.next(); 298 String key = (String ) entry.getKey(); 299 int idx; 300 while ((idx = str.indexOf(key)) >= 0) { 301 StringBuffer buf = new StringBuffer (100); 302 buf.append(str.substring(0, idx)); 303 buf.append(entry.getValue()); 304 buf.append(str.substring(idx + key.length())); 305 str = buf.toString(); 306 } 307 } 308 return str; 309 } 310 } | Popular Tags |