| /******************************************************************************* |
| * Copyright (c) 2005, 2007 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: |
| * Ian Trimble - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jst.jsf.facelet.core.internal.registry.taglib; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.concurrent.atomic.AtomicLong; |
| |
| import javax.xml.parsers.ParserConfigurationException; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResourceChangeEvent; |
| import org.eclipse.core.resources.IResourceChangeListener; |
| import org.eclipse.core.resources.IResourceDelta; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.jst.jsf.common.internal.managedobject.AbstractManagedObject; |
| import org.eclipse.jst.jsf.common.internal.managedobject.ObjectManager.ManagedObjectException; |
| import org.eclipse.jst.jsf.common.internal.resource.IResourceLifecycleListener; |
| import org.eclipse.jst.jsf.common.internal.resource.ResourceLifecycleEvent; |
| import org.eclipse.jst.jsf.common.internal.resource.ResourceSingletonObjectManager; |
| import org.eclipse.jst.jsf.common.internal.resource.ResourceLifecycleEvent.EventType; |
| import org.eclipse.jst.jsf.facelet.core.internal.FaceletCorePlugin; |
| import org.eclipse.jst.jsf.facelet.core.internal.registry.taglib.Listener.TaglibChangedEvent; |
| import org.eclipse.jst.jsf.facelet.core.internal.registry.taglib.Listener.TaglibChangedEvent.CHANGE_TYPE; |
| import org.eclipse.jst.jsf.facelet.core.internal.registry.taglib.WebappConfiguration.WebappListener; |
| import org.eclipse.jst.jsf.facelet.core.internal.registry.taglib.faceletTaglib.FaceletTaglibDefn; |
| import org.xml.sax.SAXException; |
| |
| /** |
| * Attempts to locate Facelet taglib's specified as xml files in project |
| * relative paths specified in the Facelet.LIBRARIES servlet parameters. |
| * |
| * @author Based on class in org.eclipse.jst.jsf.coreby Ian Trimble - Oracle |
| * |
| * TODO:merge back with common code in JSFAppConfig framework |
| */ |
| /* package */class ContextParamSpecifiedFaceletTaglibLocator extends |
| AbstractFaceletTaglibLocator |
| { |
| private static final String ID = ContextParamSpecifiedFaceletTaglibLocator.class.getCanonicalName(); |
| private static final String DISPLAYNAME = Messages.ContextParamSpecifiedFaceletTaglibLocator_0; |
| private final IProject _project; |
| private final Map<String, IFaceletTagRecord> _records; |
| private final TagRecordFactory _factory; |
| private final TaglibFileManager _fileManager; |
| |
| public ContextParamSpecifiedFaceletTaglibLocator(final IProject project, |
| final TagRecordFactory factory) |
| { |
| super(ID, DISPLAYNAME); |
| _project = project; |
| _records = new HashMap<String, IFaceletTagRecord>(); |
| _factory = factory; |
| _fileManager = new TaglibFileManager(project, |
| new LibraryChangeHandler()); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @seeorg.eclipse.jst.jsf.core.jsfappconfig.AbstractJSFAppConfigLocater# |
| * startLocating() |
| */ |
| @Override |
| public void start(final IProject project) |
| { |
| _fileManager.initFiles(); |
| super.start(project); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @seeorg.eclipse.jst.jsf.core.jsfappconfig.AbstractJSFAppConfigLocater# |
| * stopLocating() |
| */ |
| @Override |
| public void stop() |
| { |
| _fileManager.dispose(); |
| } |
| |
| |
| @Override |
| protected Map<String, ? extends IFaceletTagRecord> doLocate(IProject context) |
| { |
| return findInWebRoot(); |
| } |
| |
| private Map<String, ? extends IFaceletTagRecord> findInWebRoot() |
| { |
| final List<IFile> files = _fileManager.getFiles(); |
| |
| _records.clear(); |
| |
| for (final IFile file : files) |
| { |
| if (file.exists()) |
| { |
| TaglibFileTracker tracker = null; |
| try |
| { |
| tracker = _fileManager.getInstance(file); |
| } |
| catch (final ManagedObjectException e) |
| { |
| FaceletCorePlugin.log("Creating record", e); //$NON-NLS-1$ |
| } |
| |
| final IFaceletTagRecord record = createTagRecord(file); |
| if (record != null) |
| { |
| _records.put(record.getURI(), record); |
| if (tracker != null) |
| { |
| tracker.setUri(record.getURI()); |
| } |
| } |
| } |
| } |
| |
| return _records; |
| } |
| |
| private IFaceletTagRecord createTagRecord(final IFile file) |
| { |
| InputStream is = null; |
| try |
| { |
| is = file.getContents(); |
| FaceletTaglibDefn taglib = TagModelParser.loadFromInputStream(is, null); |
| if (taglib != null) |
| { |
| return _factory.createRecords(taglib); |
| } |
| } |
| catch (final CoreException e) |
| { |
| FaceletCorePlugin |
| .log( |
| "Loading web root taglibs for project: " + _project.getName(), e); //$NON-NLS-1$ |
| } |
| catch (final IOException e) |
| { |
| FaceletCorePlugin |
| .log( |
| "Loading web root taglibs for project: " + _project.getName(), e); //$NON-NLS-1$ |
| } |
| catch (final ParserConfigurationException e) |
| { |
| FaceletCorePlugin |
| .log( |
| "Loading web root taglibs for project: " + _project.getName(), e); //$NON-NLS-1$ |
| } |
| catch (final SAXException e) |
| { |
| FaceletCorePlugin |
| .log( |
| "Loading web root taglibs for project: " + _project.getName(), e); //$NON-NLS-1$ |
| } |
| finally |
| { |
| if (is != null) |
| { |
| try |
| { |
| is.close(); |
| } |
| catch (final IOException e) |
| { |
| FaceletCorePlugin.log("Closing taglib.xml", e); //$NON-NLS-1$ |
| } |
| } |
| } |
| return null; |
| } |
| |
| private static class TaglibFileManager extends |
| ResourceSingletonObjectManager<TaglibFileTracker, IFile> |
| { |
| private final LibraryChangeHandler _handler; |
| private final WebappConfiguration _webAppConfiguration; |
| private final IResourceChangeListener _newFileListener; |
| |
| public TaglibFileManager(final IProject project, |
| final LibraryChangeHandler handler) |
| { |
| _handler = handler; |
| _webAppConfiguration = new WebappConfiguration(project); |
| // TODO: fold into LifecycleListener |
| _newFileListener = new IResourceChangeListener() |
| { |
| public void resourceChanged(final IResourceChangeEvent event) |
| { |
| // if the event is post change && has the same parent |
| // project |
| if (event.getType() == IResourceChangeEvent.POST_CHANGE |
| && event.getDelta().findMember( |
| project.getFullPath()) != null) |
| { |
| for (final IFile file : _webAppConfiguration.getFiles()) |
| { |
| final IResourceDelta delta = event.getDelta() |
| .findMember(file.getFullPath()); |
| |
| if (delta != null) |
| { |
| if (delta.getKind() == IResourceDelta.ADDED) |
| { |
| _handler.added(file); |
| } |
| } |
| } |
| } |
| } |
| }; |
| |
| ResourcesPlugin.getWorkspace().addResourceChangeListener( |
| _newFileListener); |
| } |
| |
| public List<IFile> getFiles() |
| { |
| return _webAppConfiguration.getFiles(); |
| } |
| |
| public void initFiles() |
| { |
| _webAppConfiguration.start(); |
| _webAppConfiguration.addListener(new WebappListener() |
| { |
| @Override |
| public void webappChanged(WebappChangeEvent event) |
| { |
| for (final IFile file : event.getRemoved()) |
| { |
| TaglibFileTracker tracker; |
| try |
| { |
| tracker = getInstance(file); |
| _handler.removed(tracker._uri, file); |
| } |
| catch (ManagedObjectException e) |
| { |
| FaceletCorePlugin.log("While removing for webapp change", e); //$NON-NLS-1$ |
| } |
| } |
| |
| for (final IFile file : event.getAdded()) |
| { |
| _handler.added(file); |
| } |
| } |
| }); |
| } |
| |
| @Override |
| protected TaglibFileTracker createNewInstance(final IFile file) |
| { |
| return new TaglibFileTracker(file, this, _handler); |
| } |
| |
| public void addListener(final IResourceLifecycleListener listener) |
| { |
| super.addLifecycleEventListener(listener); |
| } |
| |
| public void removeListener(final IResourceLifecycleListener listener) |
| { |
| super.removeLifecycleEventListener(listener); |
| } |
| |
| public void dispose() |
| { |
| ResourcesPlugin.getWorkspace().removeResourceChangeListener( |
| _newFileListener); |
| |
| final Collection<IFile> managedResources = getManagedResources(); |
| |
| for (final IFile file : managedResources) |
| { |
| unmanageResource(file); |
| } |
| |
| _webAppConfiguration.dispose(); |
| } |
| } |
| |
| private static class TaglibFileTracker extends AbstractManagedObject |
| implements IResourceLifecycleListener |
| { |
| private final IFile _file; |
| private String _uri; |
| private final AtomicLong _lastModifiedStamp = new AtomicLong(); |
| private TaglibFileManager _manager; |
| private final LibraryChangeHandler _handler; |
| |
| public TaglibFileTracker(final IFile file, |
| final TaglibFileManager manager, |
| final LibraryChangeHandler handler) |
| { |
| _manager = manager; |
| _manager.addListener(this); |
| _file = file; |
| _lastModifiedStamp.set(file.getModificationStamp()); |
| _handler = handler; |
| } |
| |
| public final void setUri(final String uri) |
| { |
| _uri = uri; |
| } |
| |
| @Override |
| public void checkpoint() |
| { |
| // nothing currently persisted |
| |
| } |
| |
| @Override |
| public void destroy() |
| { |
| // nothing currently persisted |
| } |
| |
| @Override |
| public void dispose() |
| { |
| _manager.removeListener(this); |
| _manager = null; |
| } |
| |
| public EventResult acceptEvent(final ResourceLifecycleEvent event) |
| { |
| if (!_file.equals(event.getAffectedResource())) |
| { |
| return EventResult.getDefaultEventResult(); |
| } |
| |
| final EventType eventType = event.getEventType(); |
| |
| switch (eventType) |
| { |
| case RESOURCE_ADDED: |
| // added resources kick an add event. |
| _handler.added(_file); |
| break; |
| case RESOURCE_CHANGED: |
| // changed resources kick a change event |
| _handler.changed(_uri, _file); |
| break; |
| case RESOURCE_INACCESSIBLE: |
| // removed resources kick a remove event |
| _handler.removed(_uri, _file); |
| break; |
| } |
| |
| return EventResult.getDefaultEventResult(); |
| } |
| |
| } |
| |
| private class LibraryChangeHandler |
| { |
| public void added(final IFile file) |
| { |
| final IFaceletTagRecord tagRecord = createTagRecord(file); |
| TaglibFileTracker tracker = null; |
| try |
| { |
| tracker = _fileManager |
| .getInstance(file); |
| } |
| catch (final ManagedObjectException e) |
| { |
| FaceletCorePlugin.log("Adding new library", e); //$NON-NLS-1$ |
| } |
| |
| if (tagRecord != null) |
| { |
| |
| _records.put(tagRecord.getURI(), tagRecord); |
| if (tracker != null) |
| { |
| tracker.setUri(tagRecord.getURI()); |
| } |
| |
| fireChangeEvent(new TaglibChangedEvent( |
| ContextParamSpecifiedFaceletTaglibLocator.this, null, |
| tagRecord, CHANGE_TYPE.ADDED)); |
| } |
| } |
| |
| public void removed(final String uri, final IFile file) |
| { |
| final IFaceletTagRecord tagRecord = _records.remove(uri); |
| fireChangeEvent(new TaglibChangedEvent( |
| ContextParamSpecifiedFaceletTaglibLocator.this, tagRecord, |
| null, CHANGE_TYPE.REMOVED)); |
| } |
| |
| public void changed(final String uri, final IFile file) |
| { |
| final IFaceletTagRecord oldValue = _records.remove(uri); |
| final IFaceletTagRecord newValue = createTagRecord(file); |
| if (newValue != null) |
| { |
| _records.put(uri, newValue); |
| fireChangeEvent(new TaglibChangedEvent( |
| ContextParamSpecifiedFaceletTaglibLocator.this, |
| oldValue, newValue, CHANGE_TYPE.CHANGED)); |
| } |
| } |
| } |
| } |