/******************************************************************************* * Copyright (c) 2001, 2008 Oracle 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: * Oracle Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jst.jsf.designtime.internal.view.model.jsp.persistence; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; import org.eclipse.core.resources.IProject; import org.eclipse.jst.jsf.common.runtime.internal.view.model.common.ITagElement; import org.eclipse.jst.jsf.core.internal.JSFCorePlugin; import org.eclipse.jst.jsf.core.internal.JSFCoreTraceOptions; import org.eclipse.jst.jsf.designtime.internal.Messages; import org.eclipse.jst.jsf.designtime.internal.view.model.jsp.JSPTagResolvingStrategy; import org.eclipse.jst.jsf.designtime.internal.view.model.jsp.TLDNamespace; import org.eclipse.jst.jsf.designtime.internal.view.model.jsp.TLDTagElement; import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDDocument; import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDElementDeclaration; import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument; /** * @author cbateman * */ public class PersistedDataTagStrategy extends JSPTagResolvingStrategy { /** * the identifier of this strategy */ public final static String ID = "org.eclipse.jst.jsf.designtime.PersistedDataTagStrategy"; //$NON-NLS-1$ /** * the display name */ public final static String DISPLAY_NAME = Messages.PersistedDataTagStrategy_DisplayName; private final IProject _project; private final TagRepository _repository; private Map<String, SerializableTLDNamespace> _namespaces; private final transient AtomicBoolean _reentrancyFlag = new AtomicBoolean( false); /** * @return the descriptor for this resolver strategy */ public static StrategyDescriptor createDescriptor() { return new StrategyDescriptor(ID, DISPLAY_NAME); } /** * @param project */ public PersistedDataTagStrategy(final IProject project) { _project = project; _repository = new TagRepository(_project); } /** * */ public void init() { if (JSFCoreTraceOptions.TRACE_JSPTAGPERSISTENCE) { JSFCoreTraceOptions .log("Initializing PersistedDataTagStrategy for project: " //$NON-NLS-1$ + _project.toString()); } try { _namespaces = _repository.load(); return; } catch (final IOException e) { JSFCorePlugin .log(e, "JSP tag registry cached failed to load. Strategy will not be used"); //$NON-NLS-1$ } catch (final ClassNotFoundException e) { JSFCorePlugin .log(e, "JSP tag registry cached failed to load. Strategy will not be used"); //$NON-NLS-1$ } _namespaces = new HashMap<String, SerializableTLDNamespace>(); } /** * @param namespace * @throws ClassNotFoundException * @throws IOException */ public void save(final Map<String, TLDNamespace> namespace) throws IOException, ClassNotFoundException { if (JSFCoreTraceOptions.TRACE_JSPTAGPERSISTENCE) { JSFCoreTraceOptions .log("Saving PersistedDataTagStrategy for project: " //$NON-NLS-1$ + _project.toString()); } // namespace is considered authoritative for every key it contains // so copy them all in. However, preserve anything in our own namespace // map not found in namespace for (final Map.Entry<String, TLDNamespace> namespaceEntry : namespace .entrySet()) { final TLDNamespace ns = namespaceEntry.getValue(); final String nsName = namespaceEntry.getKey(); final SerializableTLDNamespace myNs = _namespaces.get(nsName); if (myNs == null) { if (JSFCoreTraceOptions.TRACE_JSPTAGPERSISTENCE) { JSFCoreTraceOptions.log(String.format( "Adding namespace %s for project", ns.getNSUri(), //$NON-NLS-1$ _project.toString())); } _namespaces.put(nsName, new SerializableTLDNamespace(ns)); } else { if (JSFCoreTraceOptions.TRACE_JSPTAGPERSISTENCE) { JSFCoreTraceOptions.log(String.format( "Updating namespace %s for project", ns.getNSUri(), //$NON-NLS-1$ _project.toString())); } for (final Map.Entry<String, ITagElement> elementEntry : ns .getCurrentElements().entrySet()) { if (JSFCoreTraceOptions.TRACE_JSPTAGPERSISTENCE) { JSFCoreTraceOptions.log(String.format( "Putting element %s", elementEntry.getKey())); //$NON-NLS-1$ } myNs.put(elementEntry.getKey(), elementEntry.getValue()); } } } _repository.save(_namespaces); } @Override public ITagElement resolve(final TLDElementDeclaration element) { if (JSFCoreTraceOptions.TRACE_JSPTAGPERSISTENCE) { JSFCoreTraceOptions.log(String.format( "Attempting to resolve element %s for project %s", element //$NON-NLS-1$ .getElementName(), _project)); } try { if (!_reentrancyFlag.compareAndSet(false, true)) { throw new IllegalStateException("Reentrant call to resolve"); //$NON-NLS-1$ } final String uri = getUri(element); final String tagName = element.getElementName(); if (uri != null && tagName != null) { final SerializableTLDNamespace ns = _namespaces.get(uri); if (ns != null) { final ITagElement tagElement = ns.getViewElement(tagName); if (tagElement instanceof TLDTagElement) { if (JSFCoreTraceOptions.TRACE_JSPTAGPERSISTENCE) { JSFCoreTraceOptions.log(String.format( "Resolved element %s for project %s", //$NON-NLS-1$ element.getElementName(), _project)); } return tagElement; } } } return getNotFoundIndicator(); } finally { _reentrancyFlag.set(false); } } /** * Clears all cached data and removes it permanently from disk. */ public void clear() { if (JSFCoreTraceOptions.TRACE_JSPTAGPERSISTENCE) { JSFCoreTraceOptions.log(String.format( "Flushing all data for project %s", _project)); //$NON-NLS-1$ } try { _repository.clearAll(); } catch (IOException e) { JSFCorePlugin.log(e, "Failure during cache flushing on project: " //$NON-NLS-1$ + _project); } catch (ClassNotFoundException e) { JSFCorePlugin.log(e, "Failure during cache flushing on project: " //$NON-NLS-1$ + _project); } _namespaces.clear(); } public String getDisplayName() { return DISPLAY_NAME; } private static String getUri(final TLDElementDeclaration element) { final CMDocument owner = element.getOwnerDocument(); if (owner instanceof TLDDocument) { return ((TLDDocument) owner).getUri(); } return null; } @Override public String getId() { return ID; } }