1 31 32 package org.opencms.xml; 33 34 import org.opencms.configuration.CmsConfigurationManager; 35 import org.opencms.file.CmsFile; 36 import org.opencms.file.CmsObject; 37 import org.opencms.file.CmsResource; 38 import org.opencms.main.CmsEvent; 39 import org.opencms.main.CmsLog; 40 import org.opencms.main.I_CmsEventListener; 41 import org.opencms.main.OpenCms; 42 import org.opencms.util.CmsFileUtil; 43 import org.opencms.xml.page.CmsXmlPage; 44 45 import java.io.ByteArrayInputStream ; 46 import java.io.InputStream ; 47 import java.util.Collections ; 48 import java.util.HashMap ; 49 import java.util.List ; 50 import java.util.Map ; 51 52 import org.apache.commons.collections.map.LRUMap; 53 import org.apache.commons.logging.Log; 54 55 import org.xml.sax.EntityResolver ; 56 import org.xml.sax.InputSource ; 57 58 69 public class CmsXmlEntityResolver implements EntityResolver , I_CmsEventListener { 70 71 72 public static final String OPENCMS_SCHEME = "opencms://"; 73 74 75 private static final Log LOG = CmsLog.getLog(CmsXmlEntityResolver.class); 76 77 78 private static Map m_cacheContentDefinitions; 79 80 81 private static Map m_cachePermanent; 82 83 84 private static Map m_cacheTemporary; 85 86 87 private static final String XMLPAGE_OLD_DTD_LOCATION = "org/opencms/xml/page/xmlpage.dtd"; 88 89 90 private static final String XMLPAGE_OLD_DTD_SYSTEM_ID_1 = "http://www.opencms.org/dtd/6.0/xmlpage.dtd"; 91 92 93 private static final String XMLPAGE_OLD_DTD_SYSTEM_ID_2 = "/system/shared/page.dtd"; 94 95 96 private static final String XMLPAGE_XSD_LOCATION = "org/opencms/xml/page/xmlpage.xsd"; 97 98 99 private CmsObject m_cms; 100 101 110 public CmsXmlEntityResolver(CmsObject cms) { 111 112 initCaches(); 113 m_cms = cms; 114 } 115 116 124 public static void cacheSystemId(String systemId, byte[] content) { 125 126 initCaches(); 127 m_cachePermanent.put(systemId, content); 128 } 129 130 138 protected static void initialize(CmsObject adminCms, byte[] typeSchemaBytes) { 139 140 CmsXmlEntityResolver resolver = new CmsXmlEntityResolver(adminCms); 142 143 OpenCms.addCmsEventListener(resolver, new int[] { 145 I_CmsEventListener.EVENT_CLEAR_CACHES, 146 I_CmsEventListener.EVENT_PUBLISH_PROJECT, 147 I_CmsEventListener.EVENT_RESOURCE_MODIFIED, 148 I_CmsEventListener.EVENT_RESOURCE_DELETED}); 149 150 cacheSystemId(CmsXmlContentDefinition.XSD_INCLUDE_OPENCMS, typeSchemaBytes); 152 } 153 154 157 private static void initCaches() { 158 159 if (m_cacheTemporary == null) { 160 161 LRUMap cacheTemporary = new LRUMap(128); 162 m_cacheTemporary = Collections.synchronizedMap(cacheTemporary); 163 164 HashMap cachePermanent = new HashMap (32); 165 m_cachePermanent = Collections.synchronizedMap(cachePermanent); 166 167 LRUMap cacheContentDefinitions = new LRUMap(64); 168 m_cacheContentDefinitions = Collections.synchronizedMap(cacheContentDefinitions); 169 170 if (OpenCms.getRunLevel() > OpenCms.RUNLEVEL_1_CORE_OBJECT) { 171 if ((OpenCms.getMemoryMonitor() != null) && OpenCms.getMemoryMonitor().enabled()) { 172 OpenCms.getMemoryMonitor().register( 174 CmsXmlEntityResolver.class.getName() + ".m_cacheTemporary", 175 cacheTemporary); 176 OpenCms.getMemoryMonitor().register( 178 CmsXmlEntityResolver.class.getName() + ".m_cachePermanent", 179 cachePermanent); 180 OpenCms.getMemoryMonitor().register( 182 CmsXmlEntityResolver.class.getName() + ".m_cacheContentDefinitions", 183 cacheContentDefinitions); 184 } 185 } 186 } 187 } 188 189 196 public void cacheContentDefinition(String systemId, CmsXmlContentDefinition contentDefinition) { 197 198 String cacheKey = getCacheKeyForCurrentProject(systemId); 199 m_cacheContentDefinitions.put(cacheKey, contentDefinition); 200 if (LOG.isDebugEnabled()) { 201 LOG.debug(Messages.get().getBundle().key(Messages.LOG_ER_CACHED_SYSTEM_ID_1, cacheKey)); 202 } 203 } 204 205 208 public void cmsEvent(CmsEvent event) { 209 210 CmsResource resource; 211 switch (event.getType()) { 212 case I_CmsEventListener.EVENT_PUBLISH_PROJECT: 213 case I_CmsEventListener.EVENT_CLEAR_CACHES: 214 m_cacheTemporary.clear(); 216 m_cacheContentDefinitions.clear(); 217 if (LOG.isDebugEnabled()) { 218 LOG.debug(Messages.get().getBundle().key(Messages.LOG_ER_FLUSHED_CACHES_0)); 219 } 220 break; 221 case I_CmsEventListener.EVENT_RESOURCE_MODIFIED: 222 resource = (CmsResource)event.getData().get("resource"); 223 uncacheSystemId(resource.getRootPath()); 224 break; 225 case I_CmsEventListener.EVENT_RESOURCE_DELETED: 226 List resources = (List )event.getData().get("resources"); 227 for (int i = 0; i < resources.size(); i++) { 228 resource = (CmsResource)resources.get(i); 229 uncacheSystemId(resource.getRootPath()); 230 } 231 break; 232 default: 233 } 235 } 236 237 244 public CmsXmlContentDefinition getCachedContentDefinition(String systemId) { 245 246 String cacheKey = getCacheKeyForCurrentProject(systemId); 247 CmsXmlContentDefinition result = (CmsXmlContentDefinition)m_cacheContentDefinitions.get(cacheKey); 248 if ((result != null) && LOG.isDebugEnabled()) { 249 LOG.debug(Messages.get().getBundle().key(Messages.LOG_CACHE_LOOKUP_SUCCEEDED_1, cacheKey)); 250 } 251 return result; 252 } 253 254 257 public InputSource resolveEntity(String publicId, String systemId) { 258 259 byte[] content; 261 content = (byte[])m_cachePermanent.get(systemId); 262 if (content != null) { 263 264 return new InputSource (new ByteArrayInputStream (content)); 266 } else if (systemId.equals(CmsXmlPage.XMLPAGE_XSD_SYSTEM_ID)) { 267 268 try { 270 InputStream stream = getClass().getClassLoader().getResourceAsStream(XMLPAGE_XSD_LOCATION); 271 content = CmsFileUtil.readFully(stream); 272 m_cachePermanent.put(systemId, content); 274 return new InputSource (new ByteArrayInputStream (content)); 275 } catch (Throwable t) { 276 LOG.error(Messages.get().getBundle().key(Messages.LOG_XMLPAGE_XSD_NOT_FOUND_1, XMLPAGE_XSD_LOCATION), t); 277 } 278 279 } else if (systemId.equals(XMLPAGE_OLD_DTD_SYSTEM_ID_1) || systemId.endsWith(XMLPAGE_OLD_DTD_SYSTEM_ID_2)) { 280 281 try { 283 InputStream stream = getClass().getClassLoader().getResourceAsStream(XMLPAGE_OLD_DTD_LOCATION); 284 content = CmsFileUtil.readFully(stream); 286 m_cachePermanent.put(systemId, content); 287 return new InputSource (new ByteArrayInputStream (content)); 288 } catch (Throwable t) { 289 LOG.error( 290 Messages.get().getBundle().key(Messages.LOG_XMLPAGE_DTD_NOT_FOUND_1, XMLPAGE_OLD_DTD_LOCATION), 291 t); 292 } 293 } else if ((m_cms != null) && systemId.startsWith(OPENCMS_SCHEME)) { 294 295 String cacheSystemId = systemId.substring(OPENCMS_SCHEME.length() - 1); 297 String cacheKey = getCacheKey(cacheSystemId, m_cms.getRequestContext().currentProject().isOnlineProject()); 298 content = (byte[])m_cacheTemporary.get(cacheKey); 300 if (content != null) { 301 return new InputSource (new ByteArrayInputStream (content)); 302 } 303 try { 304 m_cms.getRequestContext().saveSiteRoot(); 306 m_cms.getRequestContext().setSiteRoot("/"); 307 CmsFile file = m_cms.readFile(cacheSystemId); 308 content = file.getContents(); 309 m_cacheTemporary.put(cacheKey, content); 311 if (LOG.isDebugEnabled()) { 312 LOG.debug(Messages.get().getBundle().key(Messages.LOG_ER_CACHED_SYS_ID_1, cacheKey)); 313 } 314 return new InputSource (new ByteArrayInputStream (content)); 315 } catch (Throwable t) { 316 LOG.error(Messages.get().getBundle().key(Messages.LOG_ENTITY_RESOLVE_FAILED_1, systemId), t); 317 } finally { 318 m_cms.getRequestContext().restoreSiteRoot(); 319 } 320 } else if (systemId.substring(0, systemId.lastIndexOf("/") + 1).equalsIgnoreCase( 321 CmsConfigurationManager.DEFAULT_DTD_PREFIX)) { 322 323 String location = null; 325 try { 326 String dtdFilename = systemId.substring(systemId.lastIndexOf("/") + 1); 327 location = CmsConfigurationManager.DEFAULT_DTD_LOCATION + dtdFilename; 328 InputStream stream = getClass().getClassLoader().getResourceAsStream(location); 329 content = CmsFileUtil.readFully(stream); 330 m_cachePermanent.put(systemId, content); 332 return new InputSource (new ByteArrayInputStream (content)); 333 } catch (Throwable t) { 334 LOG.error(Messages.get().getBundle().key(Messages.LOG_DTD_NOT_FOUND_1, location), t); 335 } 336 337 } 338 339 return null; 341 } 342 343 352 private String getCacheKey(String systemId, boolean online) { 353 354 if (online) { 355 return "online_".concat(systemId); 356 } 357 return "offline_".concat(systemId); 358 } 359 360 368 private String getCacheKeyForCurrentProject(String systemId) { 369 370 boolean project = (m_cms != null) ? m_cms.getRequestContext().currentProject().isOnlineProject() : false; 372 373 if (systemId.startsWith(OPENCMS_SCHEME)) { 375 systemId = systemId.substring(OPENCMS_SCHEME.length() - 1); 376 } 377 378 return getCacheKey(systemId, project); 379 } 380 381 388 private void uncacheSystemId(String systemId) { 389 390 Object o; 391 o = m_cacheTemporary.remove(getCacheKey(systemId, false)); 392 if (null != o) { 393 m_cacheContentDefinitions.clear(); 396 if (LOG.isDebugEnabled()) { 397 LOG.debug(Messages.get().getBundle().key( 398 Messages.LOG_ER_UNCACHED_SYS_ID_1, 399 getCacheKey(systemId, false))); 400 } 401 } else { 402 o = m_cacheContentDefinitions.remove(getCacheKey(systemId, false)); 404 if ((null != o) && LOG.isDebugEnabled()) { 405 LOG.debug(Messages.get().getBundle().key( 406 Messages.LOG_ER_UNCACHED_CONTENT_DEF_1, 407 getCacheKey(systemId, false))); 408 } 409 } 410 } 411 } | Popular Tags |