blob: 9fc0b6dd32a091b4fb1fa65b15c1d37151ff5a44 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005 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:
* Gerry Kessler - initial API and implementation
* Debajit Adhikary - Fixes for bug 255097 ("Request to remove input fields
* from facet install page")
*******************************************************************************/
package org.eclipse.jst.jsf.core.internal.project.facet;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.regex.Pattern;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jst.common.project.facet.core.libprov.IPropertyChangeListener;
import org.eclipse.jst.common.project.facet.core.libprov.LibraryInstallDelegate;
import org.eclipse.jst.j2ee.project.facet.IJ2EEModuleFacetInstallDataModelProperties;
import org.eclipse.jst.jsf.core.IJSFCoreConstants;
import org.eclipse.jst.jsf.core.internal.JSFCorePlugin;
import org.eclipse.jst.jsf.core.internal.Messages;
import org.eclipse.jst.jsf.core.internal.jsflibraryconfig.JSFLibraryInternalReference;
import org.eclipse.jst.jsf.core.internal.jsflibraryregistry.ArchiveFile;
import org.eclipse.jst.jsf.core.internal.jsflibraryregistry.JSFLibrary;
import org.eclipse.osgi.util.NLS;
import org.eclipse.wst.common.componentcore.ComponentCore;
import org.eclipse.wst.common.componentcore.datamodel.FacetInstallDataModelProvider;
import org.eclipse.wst.common.componentcore.datamodel.properties.IFacetDataModelProperties;
import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
import org.eclipse.wst.common.project.facet.core.IFacetedProjectWorkingCopy;
import org.eclipse.wst.common.project.facet.core.IProjectFacetVersion;
import org.eclipse.wst.common.project.facet.core.IFacetedProject.Action;
/**
* Provides a data model used by the JSF facet install.
*
* @author Gerry Kessler - Oracle
*/
@SuppressWarnings("deprecation")
public class JSFFacetInstallDataModelProvider extends
FacetInstallDataModelProvider implements
IJSFFacetInstallDataModelProperties {
private static final String REGEX_FOR_VALID_CONFIG_FILE_NAME = "^(?!.*/{2,}.*$)[-\\w/.]+$"; //$NON-NLS-1$
private static final Pattern PATTERN_FOR_VALID_CONFIG_FILE_NAME = Pattern.compile(REGEX_FOR_VALID_CONFIG_FILE_NAME);
private final boolean jsfFacetConfigurationEnabled = JsfFacetConfigurationUtil.isJsfFacetConfigurationEnabled();
private LibraryInstallDelegate libraryInstallDelegate = null;
private void initLibraryInstallDelegate()
{
final IFacetedProjectWorkingCopy fpjwc = (IFacetedProjectWorkingCopy) getProperty( FACETED_PROJECT_WORKING_COPY );
final IProjectFacetVersion fv = (IProjectFacetVersion) getProperty( FACET_VERSION );
if( this.libraryInstallDelegate == null && fpjwc != null && fv != null )
{
this.libraryInstallDelegate = new LibraryInstallDelegate( fpjwc, fv );
this.libraryInstallDelegate.addListener
(
new IPropertyChangeListener()
{
public void propertyChanged( final String property,
final Object oldValue,
final Object newValue )
{
final IDataModel dm = getDataModel();
if( dm != null )
{
dm.notifyPropertyChange( LIBRARY_PROVIDER_DELEGATE, IDataModel.VALUE_CHG );
}
}
}
);
}
}
private String errorMessage;
public Set getPropertyNames() {
Set names = super.getPropertyNames();
if (jsfFacetConfigurationEnabled)
{
names.add(CONFIG_PATH);
names.add(SERVLET_NAME);
names.add(SERVLET_CLASSNAME);
names.add(SERVLET_URL_PATTERNS);
names.add(COMPONENT_LIBRARIES);
names.add(WEBCONTENT_DIR);
}
names.add(LIBRARY_PROVIDER_DELEGATE);
return names;
}
public Object getDefaultProperty(String propertyName) {
if (propertyName.equals(CONFIG_PATH)) {
return JSFUtils.JSF_DEFAULT_CONFIG_PATH;
} else if (propertyName.equals(SERVLET_NAME)) {
return JSFUtils.JSF_DEFAULT_SERVLET_NAME;
} else if (propertyName.equals(SERVLET_CLASSNAME)) {
return JSFUtils.JSF_SERVLET_CLASS;
} else if (propertyName.equals(SERVLET_URL_PATTERNS)) {
return new String[] {JSFUtils.JSF_DEFAULT_URL_MAPPING };
} else if (propertyName.equals(FACET_ID)) {
return IJSFCoreConstants.JSF_CORE_FACET_ID;
} else if (propertyName.equals(WEBCONTENT_DIR)){
return "WebContent"; //not sure I need this //$NON-NLS-1$
} else if (propertyName.equals(LIBRARY_PROVIDER_DELEGATE)) {
return this.libraryInstallDelegate;
} else if (propertyName.equals(COMPONENT_LIBRARIES)) {
return new JSFLibraryInternalReference[0];
}
return super.getDefaultProperty(propertyName);
}
@Override
public boolean propertySet( final String propertyName,
final Object propertyValue )
{
if( propertyName.equals( FACETED_PROJECT_WORKING_COPY ) || propertyName.equals( FACET_VERSION ) )
{
initLibraryInstallDelegate();
if( this.libraryInstallDelegate != null && propertyName.equals( FACET_VERSION ) )
{
final IProjectFacetVersion fv = (IProjectFacetVersion) getProperty( FACET_VERSION );
this.libraryInstallDelegate.setProjectFacetVersion( fv );
}
}
return super.propertySet( propertyName, propertyValue );
}
public IStatus validate(String name) {
errorMessage = null;
if (jsfFacetConfigurationEnabled)
{
if (name.equals(CONFIG_PATH)) {
return validateConfigLocation(getStringProperty(CONFIG_PATH));
} else if (name.equals(SERVLET_NAME)) {
return validateServletName(getStringProperty(SERVLET_NAME));
}
else if (name.equals(COMPONENT_LIBRARIES)) {
return validateClasspath();
}
}
if (name.equals(LIBRARY_PROVIDER_DELEGATE))
{
return ((LibraryInstallDelegate) getProperty(LIBRARY_PROVIDER_DELEGATE)).validate();
}
return super.validate(name);
}
private IStatus createErrorStatus(String msg) {
return new Status(IStatus.ERROR, JSFCorePlugin.PLUGIN_ID, msg);
}
private IStatus validateServletName(String servletName) {
if (servletName == null || servletName.trim().length() == 0) {
errorMessage = Messages.JSFFacetInstallDataModelProvider_ValidateServletName;
return createErrorStatus(errorMessage);
}
return OK_STATUS;
}
private IStatus validateConfigLocation(String text) {
if (text == null || text.trim().equals("")) { //$NON-NLS-1$
errorMessage = Messages.JSFFacetInstallDataModelProvider_ValidateConfigFileEmpty;
return createErrorStatus(errorMessage);
}
text = text.trim();
if (getProjectPath() == null) //this circumstance occurs on page init
return OK_STATUS;
IPath fullPath = getProjectPath().append(text);
IPath passedPath = new Path(text);
if (!fullPath.isValidPath(text)){
errorMessage = Messages.JSFFacetInstallDataModelProvider_ValidateConfigFilePath;
return createErrorStatus(errorMessage);
}
//FIXME: check for valid file path also [passedPath.toFile().isFile()]
if (text.toLowerCase().lastIndexOf(".xml") != text.length() - 4) { //$NON-NLS-1$
errorMessage = Messages.JSFFacetInstallDataModelProvider_ValidateConfigFileXML;
return createErrorStatus(errorMessage);
}
// Configuration path must not contain backslashes.
// Must use forward slashes instead.
if (text.lastIndexOf("\\") >= 0){ //$NON-NLS-1$
errorMessage = Messages.JSFFacetInstallDataModelProvider_ValidateConfigFileSlashes;
return createErrorStatus(errorMessage);
}
// Configuration file must NOT be absolute path.
// It must be specified relative to project.
if (passedPath.getDevice() != null) {
errorMessage = NLS.bind(
Messages.JSFFacetInstallDataModelProvider_ValidateConfigFileRelative1,
getWebContentFolderName());
return createErrorStatus(errorMessage);
}
// Configuration file must be located in the project's folder
IPath webContentFolder = getWebContentFolder();
IPath setPath = webContentFolder.append(passedPath);
if (!getWebContentFolder().isPrefixOf(setPath)) {
errorMessage = NLS.bind(
Messages.JSFFacetInstallDataModelProvider_ValidateConfigFileRelative2,
getWebContentFolderName());
return createErrorStatus(errorMessage);
}
// Check for other general invalid characters
if (!isValidConfigFileName(text))
{
errorMessage = Messages.JSFFacetInstallDataModelProvider_INVALID_JSF_CONFIG_FILE_NAME;
return createErrorStatus(errorMessage);
}
return OK_STATUS;
}
/**
* (This method had been made protected to enable JUnit testing.)
*
* @param configFileName
* @return True if the argument config file name does not have any invalid
* characters.
*/
public static boolean isValidConfigFileName (final String configFileName)
{
return PATTERN_FOR_VALID_CONFIG_FILE_NAME.matcher(configFileName).matches();
}
private IStatus validateClasspath(){
Set jars = new HashSet();
if (doesProjectExist()){
//validate actual classpath by loading jars from cp
try {
IClasspathEntry[] entries = getJavaProject().getResolvedClasspath(true);
for (int i=0;i<entries.length;i++){
IClasspathEntry entry = entries[i];
if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY){
jars.add(entry.getPath().makeAbsolute().toString());
}
}
} catch (JavaModelException e) {
// FIXME: what should we do in this case?
JSFCorePlugin.log(e, "Error searching class path"); //$NON-NLS-1$
}
}
//else as we do not have a javaProject yet, all we can do is validate that there is no duplicate jars (absolute path)
IStatus status = null;
JSFLibraryInternalReference[] compLibs = (JSFLibraryInternalReference[]) getProperty(IJSFFacetInstallDataModelProperties.COMPONENT_LIBRARIES);
if (compLibs != null){
for (int i=0;i<compLibs.length;i++){
JSFLibrary lib = compLibs[i].getLibrary();
status = checkForDupeArchiveFiles(jars, lib);
if (!OK_STATUS.equals(status)){
return status;
}
}
}
return OK_STATUS;
}
private IJavaProject getJavaProject() {
IProject proj = getProject();
if (proj != null)
return JavaCore.create(proj);
return null;
}
private IProject getProject(){
String projName = (String)getProperty(FACET_PROJECT_NAME);
if (projName == null || "".equals(projName)) //$NON-NLS-1$
return null;
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projName);
return project;
}
private boolean doesProjectExist() {
IProject project = getProject();
return (project != null) && project.exists();
}
private IStatus checkForDupeArchiveFiles(Set jars,
JSFLibrary aJSFLib) {
if (aJSFLib == null)
return OK_STATUS;
for (Iterator it=aJSFLib.getArchiveFiles().iterator();it.hasNext();){
ArchiveFile jar = (ArchiveFile)it.next();
if (jars.contains(jar.getResolvedSourceLocation())){
return createErrorStatus(NLS.bind(Messages.JSFFacetInstallDataModelProvider_DupeJarValidation,jar.getResolvedSourceLocation()));
}
jars.add(jar.getResolvedSourceLocation());
}
return OK_STATUS;
}
private IPath getProjectPath() {
IProject project = getProject();
if (project == null)
return null;
else if (project.exists())
return project.getLocation();
String projName = (String)getProperty(FACET_PROJECT_NAME);
IFacetedProjectWorkingCopy projModel = (IFacetedProjectWorkingCopy)getProperty(FACETED_PROJECT_WORKING_COPY );
if (projModel.getProjectLocation() != null)
return projModel.getProjectLocation().append(projName);
return ResourcesPlugin.getWorkspace().getRoot().getRawLocation().append(projName);
}
private IPath getWebContentFolder() {
//One can get here 2 ways:
//if web app exists and user is adding a facet, or
// if creating a new web app.
IPath webContentPath = null;
String projName = model.getStringProperty(IFacetDataModelProperties.FACET_PROJECT_NAME);
IProject proj = ResourcesPlugin.getWorkspace().getRoot()
.getProject(projName);
String webFolder = getWebContentFolderName();
if (proj.exists()) {
webContentPath = ComponentCore.createComponent(proj).getRootFolder()
.getUnderlyingFolder().getRawLocation();
}
else {
if (webFolder == null){
//we got problems... should not happen
return proj.getFullPath();
}
webContentPath = proj.getFullPath().append(webFolder);
}
return webContentPath;
}
private String getWebContentFolderName() {
String projName = (String)getProperty(FACET_PROJECT_NAME);
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projName);
if (project.exists()){
IPath webContentPath = ComponentCore.createComponent(project).getRootFolder()
.getUnderlyingFolder().getProjectRelativePath();
return webContentPath.toString();
}
IFacetedProjectWorkingCopy projWC = (IFacetedProjectWorkingCopy)getProperty(FACETED_PROJECT_WORKING_COPY);
Set<Action> pfas = projWC.getProjectFacetActions();
for (Action action : pfas){
if (action.getProjectFacetVersion().getProjectFacet().getId().equals("jst.web")){ //$NON-NLS-1$
IDataModel webFacet = (IDataModel) action.getConfig();
return webFacet.getStringProperty(IJ2EEModuleFacetInstallDataModelProperties.CONFIG_FOLDER );
}
}
//should not get here.
return null;
}
}