blob: e65ba9a4ddb9fce44179c992b971ce86b9420c6c [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.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
import java.util.concurrent.CopyOnWriteArrayList;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jst.j2ee.common.ParamValue;
import org.eclipse.jst.j2ee.internal.J2EEVersionConstants;
import org.eclipse.jst.j2ee.model.IModelProvider;
import org.eclipse.jst.j2ee.model.ModelProviderManager;
import org.eclipse.jst.j2ee.web.componentcore.util.WebArtifactEdit;
import org.eclipse.jst.j2ee.webapplication.ContextParam;
import org.eclipse.jst.j2ee.webapplication.WebApp;
import org.eclipse.jst.jsf.core.internal.JSFCorePlugin;
import org.eclipse.jst.jsf.core.jsfappconfig.JSFAppConfigUtils;
import org.eclipse.jst.jsf.facelet.core.internal.FaceletCorePlugin;
import org.eclipse.jst.jsf.facelet.core.internal.registry.taglib.WebappConfiguration.WebappListener.WebappChangeEvent;
import org.eclipse.wst.common.componentcore.resources.IVirtualFile;
import org.eclipse.wst.common.componentcore.resources.IVirtualFolder;
/**
* Manages the web.xml elements of interest to Facelet tag libraries
*
* @author cbateman
*
*/
public class WebappConfiguration
{
// TODO: move these to jsf core.
private static final String FACELET_10_LIBRARIES_CONTEXT_PARAM_NAME = "facelets.LIBRARIES"; //$NON-NLS-1$
private static final String JSF20_FACELET_LIBRARIES_CONTEXT_PARAM_NAME = "javax.faces.FACELETS_LIBRARIES"; //$NON-NLS-1$
private final IProject _project;
/**
* Cached instance of ContextParamAdapter.
*/
private final ContextParamAdapter _contextParamAdapter;
private List<IFile> _cachedFiles;
/**
* @param project
*/
/*package*/ WebappConfiguration(final IProject project)
{
_project = project;
_contextParamAdapter = new ContextParamAdapter();
}
/**
* @param listener
*/
public void addListener(final WebappListener listener)
{
_contextParamAdapter.addListener(listener);
}
/**
* @param listener
*/
public void removeListener(final WebappListener listener)
{
_contextParamAdapter.removeListener(listener);
}
/**
* @return the list of IFile's
*/
public List<IFile> getFiles()
{
final IVirtualFolder folder = JSFAppConfigUtils
.getWebContentFolder(_project);
if (folder == null)
{
return Collections.emptyList();
}
final List<String> filenames = getConfigFilesFromContextParam(_project);
final List<IFile> files = new ArrayList<IFile>();
for (final String filename : filenames)
{
final IVirtualFile vfile = folder.getFile(new Path(filename));
if (vfile != null)
{
files.add(vfile.getUnderlyingFile());
}
}
_cachedFiles = files;
return Collections.unmodifiableList(files);
}
private Object getModelObject()
{
final IModelProvider provider = ModelProviderManager
.getModelProvider(_project);
return provider.getModelObject();
}
/**
*
*/
public void start()
{
final Object webAppObj = getModelObject();
if (webAppObj != null)
{
if (webAppObj instanceof WebApp)
{
startLocatingJ2EEConfigs((WebApp) webAppObj);
}
else if (webAppObj instanceof org.eclipse.jst.javaee.web.WebApp)
{
startLocatingJEEConfigs((org.eclipse.jst.javaee.web.WebApp) webAppObj);
}
}
else
{
FaceletCorePlugin
.log(
"Could not get webApp for project: " + _project, new Exception()); //$NON-NLS-1$
}
}
/**
*
*/
public void dispose()
{
if (_contextParamAdapter != null)
{
final Object webAppObj = getModelObject();
if (webAppObj != null)
{
if (webAppObj instanceof WebApp)
{
stopLocatingJ2EEConfigs((WebApp) webAppObj);
}
else if (webAppObj instanceof org.eclipse.jst.javaee.web.WebApp)
{
stopLocatingJEEConfigs((org.eclipse.jst.javaee.web.WebApp) webAppObj);
}
}
else
{
FaceletCorePlugin
.log(
"Failed stopping locator for project: " + _project.getName() //$NON-NLS-1$
, new Exception());
}
//_contextParamAdapter.dispose();
}
}
private void startLocatingJ2EEConfigs(final WebApp webApp)
{
webApp.eAdapters().add(_contextParamAdapter);
final EList contexts = webApp.getContexts();
if (contexts != null)
{
final Iterator itContexts = contexts.iterator();
while (itContexts.hasNext())
{
final ContextParam contextParam = (ContextParam) itContexts
.next();
contextParam.eAdapters().add(_contextParamAdapter);
}
}
final EList contextParams = webApp.getContextParams();
if (contextParams != null)
{
final Iterator itContextParams = contextParams.iterator();
while (itContextParams.hasNext())
{
final ParamValue paramValue = (ParamValue) itContextParams
.next();
paramValue.eAdapters().add(_contextParamAdapter);
}
}
}
private void startLocatingJEEConfigs(
final org.eclipse.jst.javaee.web.WebApp webApp)
{
((EObject) webApp).eAdapters().add(_contextParamAdapter);
// System.out.println(((EObject)webApp).eDeliver());
final List params = webApp.getContextParams();
if (params != null)
{
final Iterator itContexts = params.iterator();
while (itContexts.hasNext())
{
final EObject contextParam = (EObject) itContexts.next();
contextParam.eAdapters().add(_contextParamAdapter);
}
}
}
private void stopLocatingJ2EEConfigs(final WebApp webApp)
{
webApp.eAdapters().remove(_contextParamAdapter);
final EList contexts = webApp.getContexts();
if (contexts != null)
{
final Iterator itContexts = contexts.iterator();
while (itContexts.hasNext())
{
final ContextParam contextParam = (ContextParam) itContexts
.next();
contextParam.eAdapters().remove(_contextParamAdapter);
}
}
final EList contextParams = webApp.getContextParams();
if (contextParams != null)
{
final Iterator itContextParams = contextParams.iterator();
while (itContextParams.hasNext())
{
final ParamValue paramValue = (ParamValue) itContextParams
.next();
paramValue.eAdapters().remove(_contextParamAdapter);
}
}
}
private void stopLocatingJEEConfigs(
final org.eclipse.jst.javaee.web.WebApp webApp)
{
((EObject) webApp).eAdapters().remove(_contextParamAdapter);
final List contextParams = webApp.getContextParams();
if (contextParams != null)
{
final Iterator itContextParams = contextParams.iterator();
while (itContextParams.hasNext())
{
final EObject paramValue = (EObject) itContextParams.next();
paramValue.eAdapters().remove(_contextParamAdapter);
}
}
}
/**
* Gets list of application configuration file names as listed in the JSF
* CONFIG_FILES context parameter ("javax.faces.CONFIG_FILES"). Will return
* an empty list if WebArtifactEdit is null, if WebApp is null, if context
* parameter does not exist, or if trimmed context parameter's value is an
* empty String.
*
* @param project
* IProject instance for which to get the context parameter's
* value.
* @return List of application configuration file names as listed in the JSF
* CONFIG_FILES context parameter ("javax.faces.CONFIG_FILES"); list
* may be empty.
*/
public static List<String> getConfigFilesFromContextParam(
final IProject project)
{
List<String> filesList = Collections.EMPTY_LIST;
if (JSFAppConfigUtils.isValidJSFProject(project))
{
final IModelProvider provider = ModelProviderManager
.getModelProvider(project);
final Object webAppObj = provider.getModelObject();
if (webAppObj != null)
{
if (webAppObj instanceof WebApp)
{
filesList = getConfigFilesForJ2EEApp(project);
}
else if (webAppObj instanceof org.eclipse.jst.javaee.web.WebApp)
{
filesList = getConfigFilesForJEEApp((org.eclipse.jst.javaee.web.WebApp) webAppObj);
}
}
}
return filesList;
}
private static List<String> getConfigFilesForJEEApp(
final org.eclipse.jst.javaee.web.WebApp webApp)
{
String filesString = null;
final List contextParams = webApp.getContextParams();
final Iterator itContextParams = contextParams.iterator();
while (itContextParams.hasNext())
{
final org.eclipse.jst.javaee.core.ParamValue paramValue = (org.eclipse.jst.javaee.core.ParamValue) itContextParams
.next();
if (paramValue.getParamName().equals(
FACELET_10_LIBRARIES_CONTEXT_PARAM_NAME)||
paramValue.getParamName().equals(
JSF20_FACELET_LIBRARIES_CONTEXT_PARAM_NAME))
{
filesString = paramValue.getParamValue();
break;
}
}
return parseFilesString(filesString);
}
private static List<String> getConfigFilesForJ2EEApp(final IProject project)
{
List filesList = new ArrayList();
final WebArtifactEdit webArtifactEdit = WebArtifactEdit
.getWebArtifactEditForRead(project);
if (webArtifactEdit != null)
{
try
{
WebApp webApp = null;
try
{
webApp = webArtifactEdit.getWebApp();
}
catch (final ClassCastException cce)
{
// occasionally thrown from WTP code in RC3 and possibly
// later
JSFCorePlugin.log(IStatus.ERROR, cce.getLocalizedMessage(),
cce);
return filesList;
}
if (webApp != null)
{
String filesString = null;
// need to branch here due to model version differences
// (BugZilla #119442)
if (webApp.getVersionID() == J2EEVersionConstants.WEB_2_3_ID)
{
final EList contexts = webApp.getContexts();
final Iterator itContexts = contexts.iterator();
while (itContexts.hasNext())
{
final ContextParam contextParam = (ContextParam) itContexts
.next();
if (contextParam.getParamName().equals(
FACELET_10_LIBRARIES_CONTEXT_PARAM_NAME)||
contextParam.getParamName().equals(
JSF20_FACELET_LIBRARIES_CONTEXT_PARAM_NAME))
// if (contextParam.getParamName().equals(
// FACELET_LIBRARIES_CONTEXT_PARAM_NAME))
{
filesString = contextParam.getParamValue();
break;
}
}
}
else
{
final EList contextParams = webApp.getContextParams();
final Iterator itContextParams = contextParams
.iterator();
while (itContextParams.hasNext())
{
final ParamValue paramValue = (ParamValue) itContextParams
.next();
if (paramValue.getName().equals(
FACELET_10_LIBRARIES_CONTEXT_PARAM_NAME)||
paramValue.getName().equals(
JSF20_FACELET_LIBRARIES_CONTEXT_PARAM_NAME))
// if (paramValue.getName().equals(
// FACELET_LIBRARIES_CONTEXT_PARAM_NAME))
{
filesString = paramValue.getValue();
break;
}
}
}
filesList = parseFilesString(filesString);
}
}
finally
{
webArtifactEdit.dispose();
}
}
return filesList;
}
private static List parseFilesString(final String filesString)
{
final List filesList = new ArrayList();
if (filesString != null && filesString.trim().length() > 0)
{
final StringTokenizer stFilesString = new StringTokenizer(
filesString, ";"); //$NON-NLS-1$
while (stFilesString.hasMoreTokens())
{
final String configFile = stFilesString.nextToken().trim();
filesList.add(configFile);
}
}
return filesList;
}
/**
* Adapter implementation used to monitor addition/removal of context-param
* nodes and change in name of existing nodes in order to respond to changes
* to the JSF CONFIG_FILES context-param.
*
* @author Ian Trimble - Oracle
*/
private class ContextParamAdapter extends AdapterImpl
{
private final CopyOnWriteArrayList<WebappListener> _listeners = new CopyOnWriteArrayList<WebappListener>();
public void addListener(final WebappListener listener)
{
_listeners.addIfAbsent(listener);
}
public void removeListener(final WebappListener listener)
{
_listeners.remove(listener);
}
private void fireEvent(final WebappChangeEvent event)
{
for (final WebappListener listener : _listeners)
{
listener.webappChanged(event);
}
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.emf.common.notify.impl.AdapterImpl#notifyChanged(org.
* eclipse.emf.common.notify.Notification)
*/
@Override
public void notifyChanged(final Notification notification)
{
final Object objNotifier = notification.getNotifier();
// System.out.println(objNotifier.toString());
if (objNotifier instanceof WebApp
|| objNotifier instanceof org.eclipse.jst.javaee.web.WebApp)
{
final int eventType = notification.getEventType();
switch (eventType)
{
case Notification.ADD:
final Object objNewValue = notification.getNewValue();
if (objNewValue instanceof ContextParam
|| objNewValue instanceof org.eclipse.jst.javaee.core.ParamValue)
{
contextParamAdded((EObject) objNewValue);
}
else if (objNewValue instanceof ParamValue)
{
paramValueAdded((EObject) objNewValue);
}
break;
case Notification.REMOVE:
final Object objOldValue = notification.getOldValue();
if (objOldValue instanceof ContextParam
|| objOldValue instanceof org.eclipse.jst.javaee.core.ParamValue)
{
contextParamRemoved((EObject) objOldValue);
}
else if (objOldValue instanceof ParamValue)
{
paramValueRemoved((EObject) objOldValue);
}
break;
}
}
// else if (objNotifier instanceof ContextParam
// || objNotifier instanceof org.eclipse.jst.javaee.core.ParamValue)
// {
// if (notification.getEventType() != Notification.REMOVING_ADAPTER)
// {
// _listener
// .tagLibChanged(ContextParamSpecifiedFaceletTaglibLocator.this);
// }
// }
// else if (objNotifier instanceof ParamValue)
// {
// if (notification.getEventType() != Notification.REMOVING_ADAPTER)
// {
// _listener
// .tagLibChanged(ContextParamSpecifiedFaceletTaglibLocator.this);
// }
// }
}
/**
* Called when a new ContextParam instance is added.
*
* @param contextParam
* ContextParam instance.
*/
protected void contextParamAdded(final EObject contextParam)
{
if (isConfigFilesContextParam(contextParam))
{
checkAndFireFileChanges();
}
contextParam.eAdapters().add(this);
}
private void checkAndFireFileChanges()
{
final List<IFile> oldFiles = _cachedFiles;
final List<IFile> newFiles = getFiles();
final List<IFile> filesAdded = new ArrayList<IFile>();
final List<IFile> filesRemoved = new ArrayList<IFile>();
for (final IFile oldFile : oldFiles)
{
if (!newFiles.contains(oldFile))
{
filesRemoved.add(oldFile);
}
}
for (final IFile newFile : newFiles)
{
if (!oldFiles.contains(newFile))
{
filesAdded.add(newFile);
}
}
if (filesAdded.size() > 0 || filesRemoved.size() > 0)
{
fireEvent(new WebappChangeEvent(filesRemoved, filesAdded));
}
}
/**
* Called when a new ParamValue instance is added.
*
* @param paramValue
* ParamValue instance.
*/
protected void paramValueAdded(final EObject paramValue)
{
if (isConfigFilesParamValue(paramValue))
{
checkAndFireFileChanges();
}
paramValue.eAdapters().add(this);
}
/**
* Called when a ContextParam instance is removed.
*
* @param contextParam
* ContextParam instance.
*/
protected void contextParamRemoved(final EObject contextParam)
{
if (isConfigFilesContextParam(contextParam))
{
checkAndFireFileChanges();
}
contextParam.eAdapters().remove(this);
}
/**
* Called when a ParamValue instance is removed.
*
* @param paramValue
* ParamValue instance.
*/
protected void paramValueRemoved(final EObject paramValue)
{
if (isConfigFilesParamValue(paramValue))
{
checkAndFireFileChanges();
}
paramValue.eAdapters().remove(this);
}
/**
* Tests if the passed ContextParam instance is the JSF CONFIG_FILES
* context parameter.
*
* @param contextParam
* ContextParam instance.
* @return true if the passed ContextParam instance is the JSF
* CONFIG_FILES context parameter, else false
*/
protected boolean isConfigFilesContextParam(final EObject contextParam)
{
boolean isConfigFiles = false;
if (contextParam != null)
{
String name = null;
if (contextParam instanceof ContextParam)
{
name = ((ContextParam) contextParam).getParamName();
}
else if (contextParam instanceof org.eclipse.jst.javaee.core.ParamValue)
{
name = ((org.eclipse.jst.javaee.core.ParamValue) contextParam)
.getParamName();
}
if (FACELET_10_LIBRARIES_CONTEXT_PARAM_NAME.equals(name)||
JSF20_FACELET_LIBRARIES_CONTEXT_PARAM_NAME.equals(name))
{
isConfigFiles = true;
}
}
return isConfigFiles;
}
/**
* Tests if the passed ParamValue instance is the JSF CONFIG_FILES
* context parameter.
*
* @param paramVal
* as EObject ParamValue instance.
* @return true if the passed ParamValue instance is the JSF
* CONFIG_FILES context parameter, else false
*/
protected boolean isConfigFilesParamValue(final EObject paramVal)
{
boolean isConfigFiles = false;
if (paramVal != null)
{
String name = null;
if (paramVal instanceof ParamValue)
{
name = ((ParamValue) paramVal).getName();
}
else if (paramVal instanceof org.eclipse.jst.javaee.core.ParamValue)
{
name = ((org.eclipse.jst.javaee.core.ParamValue) paramVal)
.getParamName();
}
if (FACELET_10_LIBRARIES_CONTEXT_PARAM_NAME.equals(name)||
JSF20_FACELET_LIBRARIES_CONTEXT_PARAM_NAME.equals(name))
{
isConfigFiles = true;
}
}
return isConfigFiles;
}
}
abstract static class WebappListener
{
public static class WebappChangeEvent
{
private final List<IFile> _removed;
private final List<IFile> _added;
WebappChangeEvent(final List<IFile> removed, final List<IFile> added)
{
_removed = Collections.unmodifiableList(removed);
_added = Collections.unmodifiableList(added);
}
public final List<IFile> getRemoved()
{
return _removed;
}
public final List<IFile> getAdded()
{
return _added;
}
}
public abstract void webappChanged(final WebappChangeEvent event);
}
}