/******************************************************************************* * Copyright (c) 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * *******************************************************************************/ package org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl; import java.lang.ref.SoftReference; import java.util.HashMap; import java.util.Map; import org.eclipse.wst.sse.core.internal.util.AbstractMemoryListener; import org.eclipse.wst.xml.core.internal.Logger; import org.eclipse.wst.xml.core.internal.XMLCorePlugin; import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalog; import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogEntry; import org.eclipse.wst.xml.core.internal.catalog.provisional.INextCatalog; import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument; import org.osgi.service.event.Event; import org.osgi.service.event.EventConstants; public class GlobalCMDocumentCache { private static GlobalCMDocumentCache globalDocumentCache = new GlobalCMDocumentCache(); private Map systemCatalogEntries = getSystemCatalogEntries(); private MemoryListener memoryListener; private final static String CATEGORY = "CMDocumentGlobalCache"; //$NON-NLS-1$ protected GlobalCMDocumentCache() { Logger.trace(CATEGORY, "Cache initialized"); //$NON-NLS-1$ memoryListener = new MemoryListener(); memoryListener.connect(); } public static GlobalCMDocumentCache getInstance() { return globalDocumentCache; } public synchronized GlobalCacheQueryResponse getCMDocument(String grammarURI) { //Logger.trace(CATEGORY, "Query for: " + grammarURI); //$NON-NLS-1$ Object systemCatalogEntry = systemCatalogEntries.get(grammarURI); if(systemCatalogEntry != null) { //Logger.trace(CATEGORY, "Document " + grammarURI + " is in system catalog"); //$NON-NLS-1$ //$NON-NLS-2$ Object object = ((SoftReference)systemCatalogEntry).get(); if(object != null) { //Logger.trace(CATEGORY, "Document " + grammarURI + "is in cache, returning cached version"); //$NON-NLS-1$ //$NON-NLS-2$ return new GlobalCacheQueryResponse((CMDocument)object, true); } else { //Logger.trace(CATEGORY, "Document " + grammarURI + " is not in cache"); //$NON-NLS-1$ //$NON-NLS-2$ return new GlobalCacheQueryResponse(null, true); } } //Logger.trace(CATEGORY, "Document " + grammarURI + " is not in system catalog, not cached"); //$NON-NLS-1$ //$NON-NLS-2$ return new GlobalCacheQueryResponse(null, false); } public synchronized void putCMDocument(String grammarURI, CMDocument cmDocument) { //Logger.trace(CATEGORY, "Document: " + grammarURI + " added to global cache"); //$NON-NLS-1$ //$NON-NLS-2$ systemCatalogEntries.put(grammarURI, new SoftReference(cmDocument)); } private synchronized static HashMap getSystemCatalogEntries(){ HashMap systemCatalogURIs = new HashMap(); ICatalog systemCatalog = null; ICatalog defaultCatalog = XMLCorePlugin.getDefault().getDefaultXMLCatalog(); INextCatalog[] nextCatalogs = defaultCatalog.getNextCatalogs(); for (int i = 0; i < nextCatalogs.length; i++) { INextCatalog catalog = nextCatalogs[i]; ICatalog referencedCatalog = catalog.getReferencedCatalog(); if (referencedCatalog != null) { if (XMLCorePlugin.SYSTEM_CATALOG_ID.equals(referencedCatalog.getId())) { systemCatalog = referencedCatalog; } } } if(systemCatalog != null) { ICatalogEntry[] catalogEntries = systemCatalog.getCatalogEntries(); for (int i = 0; i < catalogEntries.length; i++) { systemCatalogURIs.put(catalogEntries[i].getURI(), new SoftReference(null)); } } return systemCatalogURIs; } public class GlobalCacheQueryResponse { private CMDocument cachedDocument; private boolean documentCacheable; public GlobalCacheQueryResponse(CMDocument cachedCMDocument, boolean documentCacheable) { this.cachedDocument = cachedCMDocument; this.documentCacheable = documentCacheable; } public CMDocument getCachedCMDocument() { return cachedDocument; } public boolean isDocumentCacheable() { return documentCacheable; } } private class MemoryListener extends AbstractMemoryListener { protected void handleMemoryEvent(Event event) { Object topic = event.getProperty(EventConstants.EVENT_TOPIC); if(SEV_SERIOUS.equals(topic) || SEV_CRITICAL.equals(topic)) { Logger.trace(CATEGORY, "Serious severity low memory event received, flushing global CMDocument cache."); //$NON-NLS-1$ systemCatalogEntries = getSystemCatalogEntries(); } } } }