blob: cf9d74d46af28d6f52caf87e67cd32208efe60e0 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008 Oracle Corporation.
* 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:
* Cameron Bateman - initial API and implementation
*******************************************************************************/
package org.eclipse.jst.jsf.facelet.core.internal.registry.taglib;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.jst.jsf.common.internal.locator.ILocatorProvider;
import org.eclipse.jst.jsf.core.internal.tld.IFaceletConstants;
import org.eclipse.jst.jsf.facelet.core.internal.FaceletCorePlugin;
/**
* Taglib descriptor for a project.
*
* @author cbateman
*
*/
public class ProjectTaglibDescriptor implements IProjectTaglibDescriptor
{
private final AtomicInteger _isInitialized = new AtomicInteger(
0);
private final IProject _project;
private final ILocatorProvider<AbstractFaceletTaglibLocator> _locatorProvider;
private final MyChangeListener _libChangeListener;
private final Map<String, IFaceletTagRecord> _tagRecords;
private final TagRecordFactory _factory;
private final AtomicBoolean _isDisposed = new AtomicBoolean(false);
private final DefaultStandardTaglibLocator _defaultTaglibLocator;
/**
* @param project
* @param factory
* @param locatorProvider
*/
public ProjectTaglibDescriptor(final IProject project, final TagRecordFactory factory,
final ILocatorProvider<AbstractFaceletTaglibLocator> locatorProvider)
{
_project = project;
_tagRecords = new HashMap<String, IFaceletTagRecord>();
_locatorProvider = locatorProvider;
_locatorProvider.initialize();
_factory = factory;
_libChangeListener = new MyChangeListener();
_defaultTaglibLocator = new DefaultStandardTaglibLocator();
_defaultTaglibLocator.start(project);
}
private void initialize()
{
if (_isInitialized.addAndGet(1) == 1)
{
synchronized (this)
{
for (final AbstractFaceletTaglibLocator locator : _locatorProvider.getLocators())
{
SafeRunner.run(new ISafeRunnable()
{
public void handleException(final Throwable exception)
{
FaceletCorePlugin
.log(
"While locating facelet libraries on project: " + _project.getName(), new Exception(exception)); //$NON-NLS-1$
}
public void run() throws Exception
{
locator.addListener(_libChangeListener);
locator.start(_project);
_tagRecords.putAll(locator.locate(_project));
}
});
}
// ensure that we add the standard tag libraries if we don't find them
// on the classpath. The spec doesn't require that taglib's are
// included in a JSF impl for these
ensureStandardLibraries(_project);
}
}
}
private void ensureStandardLibraries(final IProject project)
{
final Map<String, ? extends IFaceletTagRecord> defaultRecords = _defaultTaglibLocator.locate(project);
for (final String uri : IFaceletConstants.ALL_FACELET_TAGLIBS)
{
if (!_tagRecords.containsKey(uri))
{
IFaceletTagRecord faceletTagRecord = defaultRecords.get(uri);
if (faceletTagRecord != null)
{
_tagRecords.put(uri, faceletTagRecord);
}
else
{
FaceletCorePlugin.log("Could not find taglib for uri: "+uri, new Exception()); //$NON-NLS-1$
}
}
}
}
public Collection<? extends IFaceletTagRecord> getTagLibraries()
{
initialize();
return Collections.unmodifiableCollection(_tagRecords.values());
}
void maybeLog(final Exception e)
{
if (_isInitialized.get() <= 1)
{
FaceletCorePlugin.log("Failed initializing taglib descriptor", e); //$NON-NLS-1$
}
}
public IFaceletTagRecord getTagLibrary(final String uri)
{
initialize();
return _tagRecords.get(uri);
}
public void addListener(final Listener listener)
{
for (final AbstractFaceletTaglibLocator locator : _locatorProvider.getLocators())
{
locator.addListener(listener);
}
}
public void removeListener(final Listener listener)
{
for (final AbstractFaceletTaglibLocator locator : _locatorProvider.getLocators())
{
locator.removeListener(listener);
}
}
public void checkpoint()
{
// do nothing
}
public void destroy()
{
// call dispose; there is no persistent data to cleanup.
dispose();
}
public void dispose()
{
if (_isDisposed.compareAndSet(false, true))
{
for (final AbstractFaceletTaglibLocator locator : _locatorProvider.getLocators())
{
locator.stop();
}
_factory.dispose();
}
}
public boolean isDisposed()
{
return _isDisposed.get();
}
private class MyChangeListener extends Listener
{
@Override
public void changed(final TaglibChangedEvent event)
{
switch (event.getChangeType())
{
case ADDED:
_tagRecords.put(event.getNewValue().getURI(), event
.getNewValue());
break;
case CHANGED:
_tagRecords.put(event.getNewValue().getURI(), event
.getNewValue());
break;
case REMOVED:
_tagRecords.remove(event.getOldValue());
break;
}
}
}
}