blob: 62f95a8e21a36090de29dd3fb0e02c913e67a4ae [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2007 IBM 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jst.j2ee.internal.common;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.util.URI;
import org.eclipse.jem.util.emf.workbench.ProjectUtilities;
import org.eclipse.jst.j2ee.application.internal.operations.ClassPathSelection;
import org.eclipse.jst.j2ee.application.internal.operations.ClasspathElement;
import org.eclipse.jst.j2ee.classpathdep.ClasspathDependencyUtil;
import org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.ArchiveManifest;
import org.eclipse.jst.j2ee.componentcore.J2EEModuleVirtualComponent;
import org.eclipse.jst.j2ee.internal.J2EEConstants;
import org.eclipse.jst.j2ee.internal.plugin.J2EEPlugin;
import org.eclipse.jst.j2ee.internal.project.J2EEProjectUtilities;
import org.eclipse.jst.j2ee.project.EarUtilities;
import org.eclipse.jst.j2ee.project.JavaEEProjectUtilities;
import org.eclipse.wst.common.componentcore.ComponentCore;
import org.eclipse.wst.common.componentcore.UnresolveableURIException;
import org.eclipse.wst.common.componentcore.internal.ModuleStructuralModel;
import org.eclipse.wst.common.componentcore.internal.StructureEdit;
import org.eclipse.wst.common.componentcore.internal.impl.ModuleURIUtil;
import org.eclipse.wst.common.componentcore.internal.util.ComponentUtilities;
import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
import org.eclipse.wst.common.componentcore.resources.IVirtualReference;
import org.eclipse.wst.common.internal.emfworkbench.validateedit.ResourceStateInputProvider;
import org.eclipse.wst.common.internal.emfworkbench.validateedit.ResourceStateValidator;
import org.eclipse.wst.common.internal.emfworkbench.validateedit.ResourceStateValidatorImpl;
import org.eclipse.wst.common.internal.emfworkbench.validateedit.ResourceStateValidatorPresenter;
public class ClasspathModel implements ResourceStateInputProvider, ResourceStateValidator {
protected IProject project;
protected IVirtualComponent selectedEARComponent;
protected IVirtualComponent component;
protected IVirtualComponent[] availableEARComponents = null;
protected ClassPathSelection classPathSelection;
protected List listeners;
protected List nonResourceFiles;
protected ResourceStateValidator stateValidator;
protected ArchiveManifest manifest;
public static String NO_EAR_MESSAGE = CommonEditResourceHandler.getString("NO_EAR_JARDEP_FOR_MOD_UI_"); //$NON-NLS-1$
protected List targetWLPRefComponentList;
protected boolean isWLPModel = false;
protected ClassPathSelection classPathWLPSelection;
protected Comparator comparator = new Comparator() {
public int compare(Object o1, Object o2) {
IVirtualComponent e1 = (IVirtualComponent) o1;
IVirtualComponent e2 = (IVirtualComponent) o2;
return e1.getProject().getName().compareTo(e2.getProject().getName());
}
};
public ClasspathModel(ArchiveManifest initialManifest) {
this(initialManifest, false);
}
public ClasspathModel(ArchiveManifest initialManifest, boolean isWLPModel) {
super();
manifest = initialManifest;
this.isWLPModel = isWLPModel;
}
public IProject getProject() {
return project;
}
public void setProject(IProject project) {
this.project = project;
initializeComponent();
getAvailableEARComponents();
}
private void initializeComponent() {
setComponent(ComponentCore.createComponent(getProject()));
}
protected IVirtualComponent[] refreshAvailableEARs() {
if (component != null) {
IProject[] earProjects = EarUtilities.getReferencingEARProjects(getComponent().getProject());
availableEARComponents = ComponentUtilities.getComponents(earProjects);
if (availableEARComponents != null && availableEARComponents.length > 0) {
Arrays.sort(availableEARComponents, comparator);
if (selectedEARComponent == null || !Arrays.asList(availableEARComponents).contains(selectedEARComponent)) {
if (availableEARComponents.length > 0)
selectedEARComponent = availableEARComponents[0];
else
selectedEARComponent = null;
}
}
}
return availableEARComponents;
}
public IVirtualComponent[] getAvailableEARComponents() {
if (availableEARComponents == null)
refreshAvailableEARs();
return availableEARComponents;
}
public IVirtualComponent getSelectedEARComponent() {
return selectedEARComponent;
}
public void setSelectedEARComponent(IVirtualComponent component) {
selectedEARComponent = component;
fireNotification(new ClasspathModelEvent(ClasspathModelEvent.EAR_PROJECT_CHANGED));
}
public String getArchiveURI() {
if (selectedEARComponent != null) {
IVirtualReference [] refs = selectedEARComponent.getReferences();
IVirtualComponent moduleComp = getComponent();
for(int i=0; i<refs.length; i++){
if(refs[i].getReferencedComponent().equals(moduleComp)){
return refs[i].getArchiveName();
}
}
}
return null;
}
protected void initializeSelection(ArchiveManifest existing) {
if (!JavaEEProjectUtilities.isEARProject(getProject())) {
if (getProject() != null) {
if(existing != null){
manifest = existing;
}
}
if( existing == null )
createClassPathSelection();
else{
createClassPathSelection(manifest);
}
}
}
protected void createClassPathSelection() {
if (getComponent() != null && selectedEARComponent != null ) {
classPathSelection = new ClassPathSelection(getComponent(), selectedEARComponent);
} else if (selectedEARComponent == null) {
classPathSelection = new ClassPathSelection(getComponent());
} else {
classPathSelection = null;
}
}
protected void createClassPathSelection(ArchiveManifest manifest) {
if (getComponent() != null && selectedEARComponent != null ) {
classPathSelection = new ClassPathSelection(getComponent(), selectedEARComponent, manifest);
} else if (selectedEARComponent == null) {
classPathSelection = new ClassPathSelection(getComponent(), manifest);
} else {
classPathSelection = null;
}
}
public void dispose() {
}
public ClassPathSelection getClassPathSelection() {
if (classPathSelection == null)
initializeSelection(null);
return classPathSelection;
}
public void resetClassPathSelection(ArchiveManifest mf) {
initializeSelection(mf);
fireNotification(new ClasspathModelEvent(ClasspathModelEvent.CLASS_PATH_RESET));
}
public void resetClassPathSelection() {
resetClassPathSelection(null);
}
public void resetClassPathSelectionForWLPs() {
classPathWLPSelection = null;
}
public void addListener(ClasspathModelListener listener) {
if (listeners == null)
listeners = new ArrayList();
listeners.add(listener);
}
public void removeListener(ClasspathModelListener listener) {
if (listeners != null)
listeners.remove(listener);
}
public void fireNotification(ClasspathModelEvent evt) {
if (listeners == null)
return;
for (int i = 0; i < listeners.size(); i++) {
ClasspathModelListener listener = (ClasspathModelListener) listeners.get(i);
listener.modelChanged(evt);
}
}
/**
* Sets the isSelected for the classpath element and sends out a notification of type
* {@link ClasspathModelEvent#CLASS_PATH_CHANGED}
*/
public void setSelection(ClasspathElement element, boolean selected) {
element.setSelected(selected);
if (!isWLPModel()) {
updateManifestClasspath();
} else {
// at least fire the change event
fireNotification(new ClasspathModelEvent(ClasspathModelEvent.CLASS_PATH_CHANGED));
}
}
/**
* Select or deselect all and notify
*/
public void setAllClasspathElementsSelected(boolean selected) {
ClassPathSelection s = getClassPathSelection();
if (s != null) {
s.setAllSelected(selected);
updateManifestClasspath();
}
}
/**
* Select or deselect all and notify
*/
public void setAllClasspathElementsSelected(List elements, boolean selected) {
ClassPathSelection s = getClassPathSelection();
if (s != null) {
s.setAllSelected(elements, selected);
updateManifestClasspath();
}
}
/**
* Updates the manifest Class-Path:, and sends out a notification of type
* {@link ClasspathModelEvent#CLASS_PATH_CHANGED}
*/
public void updateManifestClasspath() {
if (classPathSelection != null && classPathSelection.isModified()) {
manifest.setClassPath(classPathSelection.toString());
fireNotification(new ClasspathModelEvent(ClasspathModelEvent.CLASS_PATH_CHANGED));
}
}
/**
* Updates the manifest Main-Class:, and sends out a notification of type
* {@link ClasspathModelEvent#MAIN_CLASS_CHANGED}
*/
public void updateMainClass(String mainClass) {
manifest.setMainClass(mainClass);
fireNotification(new ClasspathModelEvent(ClasspathModelEvent.MAIN_CLASS_CHANGED));
}
/**
* Updates the manifest Main-Class:, and sends out a notification of type
* {@link ClasspathModelEvent#MAIN_CLASS_CHANGED}
*/
public void updateImplVersion(String implVersion) {
manifest.setImplemenationVersion(implVersion);
fireNotification(new ClasspathModelEvent(ClasspathModelEvent.IMPL_VERSION_CHANGED));
}
public void fireSavedEvent() {
fireNotification(new ClasspathModelEvent(ClasspathModelEvent.MODEL_SAVED));
}
/**
* Sets the manifest without touching the archive, or notifying
*/
public void primSetManifest(ArchiveManifest mf) {
manifest = mf;
}
/**
* Sets the manfest on the archive, updates the classpath selection, and notifies
*/
public void setManifest(ArchiveManifest newManifest) {
try {
J2EEProjectUtilities.writeManifest(getProject(), newManifest);
} catch (IOException e) {
J2EEPlugin.logError(e);
}
classPathSelection = null;
getClassPathSelection(); // Ensure the selection is initialized.
fireNotification(new ClasspathModelEvent(ClasspathModelEvent.MANIFEST_CHANGED));
}
public void forceUpdateClasspath(ArchiveManifest newManifest) {
primSetManifest(newManifest);
classPathSelection = null;
initializeSelection(newManifest);
fireNotification(new ClasspathModelEvent(ClasspathModelEvent.MANIFEST_CHANGED));
}
public void selectEAR(int index) {
selectedEARComponent = availableEARComponents[index];
initializeSelection(null);
fireNotification(new ClasspathModelEvent(ClasspathModelEvent.EAR_PROJECT_CHANGED));
}
public void moveUp(List toMoveUp) {
getClassPathSelection().moveUp(toMoveUp);
updateManifestClasspath();
}
public void moveDown(List toMoveDown) {
getClassPathSelection().moveDown(toMoveDown);
updateManifestClasspath();
}
public void refresh() {
ArchiveManifest mf = null;
if (getComponent() != null)
mf = J2EEProjectUtilities.readManifest(getProject());
refreshAvailableEARs();
resetClassPathSelection(mf);
}
/**
* @see com.ibm.etools.emf.workbench.ResourceStateInputProvider#cacheNonResourceValidateState(List)
*/
public void cacheNonResourceValidateState(List roNonResourceFiles) {
}
/**
* @see com.ibm.etools.emf.workbench.ResourceStateInputProvider#getNonResourceFiles()
*/
public List getNonResourceFiles() {
if (nonResourceFiles == null)
initNonResourceFiles();
return nonResourceFiles;
}
protected void initNonResourceFiles() {
// Might be opened from a JAR
if (getComponent() == null || getComponent().isBinary()){
return;
}
nonResourceFiles = new ArrayList(1);
if(isWLPModel){
IFile dotProject = getComponent().getProject().getFile(ProjectUtilities.DOT_PROJECT);
if(dotProject != null){
nonResourceFiles.add(dotProject);
}
} else {
IFile mf = J2EEProjectUtilities.getManifestFile(getComponent().getProject());
if (mf != null){
nonResourceFiles.add(mf);
}
}
}
/**
* @see com.ibm.etools.emf.workbench.ResourceStateInputProvider#getNonResourceInconsistentFiles()
*/
public List getNonResourceInconsistentFiles() {
return null;
}
/**
* @see com.ibm.etools.emf.workbench.ResourceStateInputProvider#isDirty()
*/
public boolean isDirty() {
ClassPathSelection selection = getClassPathSelection();
if (selection == null)
return false;
return selection.isModified();
}
/**
* Return a list of all the files that will get modified as a result of running this operation;
* used for validateEdit
*/
public Set getAffectedFiles() {
Set result = new HashSet();
IFile aFile = J2EEProjectUtilities.getManifestFile(getComponent().getProject());
if (aFile != null && aFile.exists())
result.add(aFile);
result.addAll(ProjectUtilities.getFilesAffectedByClasspathChange(getComponent().getProject()));
return result;
}
/**
* @see com.ibm.etools.emf.workbench.ResourceStateInputProvider#getResources()
*/
public List getResources() {
if(isWLPModel){
StructureEdit sEdit = null;
try {
sEdit = StructureEdit.getStructureEditForWrite(project);
ModuleStructuralModel structuralModel = sEdit.getModuleStructuralModel();
List resources = new ArrayList();
resources.addAll(structuralModel.getResources());
return resources;
} catch(Exception e){
J2EEPlugin.logError(e);
return Collections.EMPTY_LIST;
}
finally {
if (sEdit !=null){
sEdit.dispose();
}
}
}
return Collections.EMPTY_LIST;
}
public boolean selectDependencyIfNecessary(IProject referencedProject) {
getClassPathSelection();
if (classPathSelection == null || classPathSelection.hasDirectOrIndirectDependencyTo(referencedProject))
return false;
ClasspathElement element = classPathSelection.getClasspathElement(referencedProject);
if (element != null) {
setSelection(element, true);
return true;
}
return false;
}
public boolean selectDependencyIfNecessary(String jarName) {
getClassPathSelection();
if (classPathSelection == null || classPathSelection.hasDirectOrIndirectDependencyTo(jarName))
return false;
ClasspathElement element = classPathSelection.getClasspathElement(jarName);
if (element != null) {
setSelection(element, true);
return true;
}
return false;
}
public void removeDependency(String jarName) {
getClassPathSelection();
if (classPathSelection == null)
return;
ClasspathElement element = classPathSelection.getClasspathElement(jarName);
if (element != null && element.isValid())
setSelection(element, false);
}
public void removeDependency(IProject referencedProject) {
getClassPathSelection();
if (classPathSelection == null)
return;
ClasspathElement element = classPathSelection.getClasspathElement(referencedProject);
if (element != null && element.isValid())
setSelection(element, false);
}
public void selectFilterLevel(int filterLevel) {
getClassPathSelection();
if (classPathSelection != null)
classPathSelection.selectFilterLevel(filterLevel);
updateManifestClasspath();
}
/**
* Gets the stateValidator.
*
* @return Returns a ResourceStateValidator
*/
public ResourceStateValidator getStateValidator() {
if (stateValidator == null)
stateValidator = createStateValidator();
return stateValidator;
}
/**
* Method createStateValidator.
*
* @return ResourceStateValidator
*/
private ResourceStateValidator createStateValidator() {
return new ResourceStateValidatorImpl(this);
}
/**
* @see ResourceStateValidator#checkActivation(ResourceStateValidatorPresenter)
*/
public void checkActivation(ResourceStateValidatorPresenter presenter) throws CoreException {
getStateValidator().checkActivation(presenter);
}
/**
* @see ResourceStateValidator#lostActivation(ResourceStateValidatorPresenter)
*/
public void lostActivation(ResourceStateValidatorPresenter presenter) throws CoreException {
getStateValidator().lostActivation(presenter);
}
/**
* @see ResourceStateValidator#validateState(ResourceStateValidatorPresenter)
*/
public IStatus validateState(ResourceStateValidatorPresenter presenter) throws CoreException {
return getStateValidator().validateState(presenter);
}
/**
* @see ResourceStateValidator#checkSave(ResourceStateValidatorPresenter)
*/
public boolean checkSave(ResourceStateValidatorPresenter presenter) throws CoreException {
return getStateValidator().checkSave(presenter);
}
/**
* @see ResourceStateValidator#checkReadOnly()
*/
public boolean checkReadOnly() {
return getStateValidator().checkReadOnly();
}
public IVirtualComponent getComponent() {
return component;
}
public void setComponent(IVirtualComponent component) {
this.component = component;
}
public ClassPathSelection getClassPathSelectionForWLPs() {
if (classPathWLPSelection == null)
initializeSelectionForWLPs();
return classPathWLPSelection;
}
//copied from WebArtifactEdit
private static IPath WEBLIB = new Path(J2EEConstants.WEB_INF_LIB).makeAbsolute();
private static IPath WEBINF_CLASSES = new Path(J2EEConstants.WEB_INF_CLASSES).makeAbsolute();
private static IVirtualReference[] getLibModules(IProject project) {
List result = new ArrayList();
IVirtualComponent comp = ComponentCore.createComponent(project);
IVirtualReference[] refComponents = null;
if (!comp.isBinary())
refComponents = ((J2EEModuleVirtualComponent)comp).getNonManifestReferences();
else
refComponents = comp.getReferences();
// Check the deployed path to make sure it has a lib parent folder and matchs the web.xml
// base path
for (int i = 0; i < refComponents.length; i++) {
if (refComponents[i].getRuntimePath().equals(WEBLIB))
result.add(refComponents[i]);
}
return (IVirtualReference[]) result.toArray(new IVirtualReference[result.size()]);
}
private void initializeSelectionForWLPs() {
classPathWLPSelection = new ClassPathSelection();
classPathWLPSelection.setFilterLevel(ClassPathSelection.FILTER_NONE);
//this is the set of all projects that are already mapped as web library projects
HashSet existingWebLibProjects = new HashSet();
List otherExistingWebLibRefs = new ArrayList();
IVirtualReference [] libModules = getLibModules(component.getProject());
for(int i=0;i<libModules.length; i++){
IVirtualComponent comp = libModules[i].getReferencedComponent();
if(comp != null && comp.exists()){
if(comp.isBinary()){
otherExistingWebLibRefs.add(libModules[i]);
} else {
IProject p = comp.getProject();
if(p != null && p.exists()){
existingWebLibProjects.add(p);
}
}
}
}
//this is the list of all projects that should show up in the list
HashSet possibleWebLibs = new HashSet();
try{
List javaProjects = J2EEProjectUtilities.getAllJavaNonFlexProjects();
possibleWebLibs.addAll(javaProjects);
} catch(CoreException e){
J2EEPlugin.logError(e);
}
IProject[] utilityProjects = J2EEProjectUtilities.getAllProjectsInWorkspaceOfType(J2EEProjectUtilities.UTILITY);
possibleWebLibs.addAll(Arrays.asList(utilityProjects));
IProject[] ejbProjects = J2EEProjectUtilities.getAllProjectsInWorkspaceOfType(J2EEProjectUtilities.EJB);
possibleWebLibs.addAll(Arrays.asList(ejbProjects));
Map pathToComp = new HashMap();
//first handle the projects case
for(Iterator iterator = possibleWebLibs.iterator(); iterator.hasNext();){
IProject possibleWebLib = (IProject)iterator.next();
if(possibleWebLib.getName().startsWith(".")){ //$NON-NLS-1$
continue;
}
boolean isExistingWebLib = existingWebLibProjects.contains(possibleWebLib);
classPathWLPSelection.createProjectElement(possibleWebLib, isExistingWebLib);
// build of map of all unique classpath component contributions from dependent projects
if(isExistingWebLib){
IVirtualComponent component = ComponentCore.createComponent(possibleWebLib);
if(component != null){
classPathWLPSelection.buildClasspathComponentDependencyMap(component, pathToComp);
}
}
}
//next handle entries for all other web lib refs
//e.g. to jars in other projects, or outside the workspace or relative to a var
for(Iterator iterator = otherExistingWebLibRefs.iterator(); iterator.hasNext();){
IVirtualReference ref = (IVirtualReference)iterator.next();
IVirtualComponent referencedComponent = ref.getReferencedComponent();
// do not add if this is a classpath entry dependency
if (ClasspathDependencyUtil.isClasspathComponentDependency(referencedComponent)) {
continue;
}
try {
String unresolvedURI = ModuleURIUtil.getArchiveName(URI.createURI(ModuleURIUtil.getHandleString(referencedComponent)));
URI archiveURI = URI.createURI(unresolvedURI);
ClasspathElement element = classPathWLPSelection.createArchiveElement(URI.createURI(ModuleURIUtil.getHandleString(referencedComponent)), referencedComponent.getName(), archiveURI.lastSegment());
classPathWLPSelection.addClasspathElement(element, unresolvedURI);
} catch (UnresolveableURIException e) {
J2EEPlugin.logError(e);
}
}
// add ClasspathElements for all dependent project cp dependencies
final Iterator it = pathToComp.values().iterator();
while (it.hasNext()) {
final IVirtualComponent c = (IVirtualComponent) it.next();
final URI archiveURI = URI.createURI(ModuleURIUtil.getHandleString(c));
String unresolvedURI = null;
try {
unresolvedURI = ModuleURIUtil.getArchiveName(archiveURI);
} catch (UnresolveableURIException e) {
J2EEPlugin.logError(e);
}
if (unresolvedURI != null) {
final ClasspathElement element = classPathWLPSelection.createClasspathArchiveElement(c.getProject(), archiveURI, unresolvedURI);
classPathWLPSelection.addClasspathElement(element, unresolvedURI);
}
}
// Add elements for raw classpath entries (either already tagged or potentially taggable)
try {
classPathWLPSelection.createClasspathEntryElements(component, WEBLIB, WEBINF_CLASSES);
} catch (CoreException ce) {
J2EEPlugin.logError(ce);
}
}
public boolean isWLPModel() {
return isWLPModel;
}
}