blob: f0ac3204faa14b8b3d85c47cf82dbd1f13a6058d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2005 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.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IContainer;
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.jdt.core.IClasspathContainer;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jem.util.emf.workbench.ProjectUtilities;
import org.eclipse.jem.util.logger.proxy.Logger;
import org.eclipse.jst.j2ee.application.internal.operations.ClassPathSelection;
import org.eclipse.jst.j2ee.application.internal.operations.ClasspathElement;
import org.eclipse.jst.j2ee.commonarchivecore.internal.Archive;
import org.eclipse.jst.j2ee.commonarchivecore.internal.EARFile;
import org.eclipse.jst.j2ee.commonarchivecore.internal.EJBJarFile;
import org.eclipse.jst.j2ee.commonarchivecore.internal.exception.DeploymentDescriptorLoadException;
import org.eclipse.jst.j2ee.commonarchivecore.internal.exception.ManifestException;
import org.eclipse.jst.j2ee.commonarchivecore.internal.exception.OpenFailureException;
import org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.ArchiveManifest;
import org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.ArchiveManifestImpl;
import org.eclipse.jst.j2ee.componentcore.util.EARArtifactEdit;
import org.eclipse.jst.j2ee.internal.J2EEConstants;
import org.eclipse.jst.j2ee.internal.common.classpath.J2EEComponentClasspathUpdater;
import org.eclipse.jst.j2ee.internal.project.J2EEProjectUtilities;
import org.eclipse.wst.common.componentcore.ComponentCore;
import org.eclipse.wst.common.componentcore.UnresolveableURIException;
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 EARFile earFile;
protected IVirtualComponent component;
protected Archive archive;
public EARArtifactEdit earArtifactEdit;
/** The EAR nature runtimes for all the open EAR projects in the workspace */
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) {
super();
manifest = initialManifest;
}
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 = J2EEProjectUtilities.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;
}
/**
* Gets the selectedEARComponent.
*
* @return Returns a EARNatureRuntime
*/
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) {
return getEARArtifactEdit().getModuleURI(getComponent());
}
return null;
}
public EARArtifactEdit getEARArtifactEdit() {
if (earArtifactEdit == null || selectedEARComponentChanged())
earArtifactEdit = EARArtifactEdit.getEARArtifactEditForRead(selectedEARComponent);
return earArtifactEdit;
}
private boolean selectedEARComponentChanged() {
if (earArtifactEdit != null && !earArtifactEdit.getComponent().getName().equals(selectedEARComponent.getName())) {
earArtifactEdit.dispose();
earArtifactEdit = null;
return true;
}
return false;
}
protected void initializeEARFile() {
if (selectedEARComponent == null || !isDDInEAR(selectedEARComponent)) {
earFile = null;
return;
}
try {
earFile = (EARFile) getEARArtifactEdit().asArchive(false);
} catch (OpenFailureException ex) {
handleOpenFailureException(ex);
}
}
/**
* initializeSelection method comment.
*/
protected void initializeSelection(ArchiveManifest existing) {
try {
initializeEARFile();
initializeArchive();
if (!J2EEProjectUtilities.isEARProject(getProject())) {
if (archive != null) {
if (existing == null) {
if (manifest != null)
archive.setManifest(manifest);
else
// Load it now because we're going to close the EAR;
// this might be a binary project
archive.getManifest();
} else
archive.setManifest(existing);
List archiveFiles = earFile.getArchiveFiles();
for (int i = 0; i < archiveFiles.size(); i++) {
Archive anArchive = (Archive) archiveFiles.get(i);
try {
if (anArchive.isEJBJarFile())
((EJBJarFile) anArchive).getDeploymentDescriptor();
anArchive.getManifest();
} catch (ManifestException mfEx) {
Logger.getLogger().logError(mfEx);
anArchive.setManifest((ArchiveManifest) new ArchiveManifestImpl());
} catch (DeploymentDescriptorLoadException ddException) {
Logger.getLogger().logError(ddException);
}
}
}
createClassPathSelection();
}
} finally {
if (earFile != null)
earFile.close();
}
}
protected void initializeArchive() {
if (!J2EEProjectUtilities.isEARProject(getProject())) {
if (earFile == null) {
archive = null;
return;
}
String uri = getArchiveURI();
if (uri != null) {
try {
archive = (Archive) earFile.getFile(uri);
} catch (java.io.FileNotFoundException ex) {
archive = null;
}
}
} else {
EARArtifactEdit edit = null;
try {
edit = EARArtifactEdit.getEARArtifactEditForRead(getProject());
archive = edit.asArchive(true);
} catch (OpenFailureException oe) {
Logger.getLogger().log(oe);
} finally {
if (edit != null)
edit.dispose();
}
}
}
protected void createClassPathSelection() {
if (archive != null)
classPathSelection = new ClassPathSelection(archive, earFile);
else
classPathSelection = null;
}
protected boolean isDDInEAR(IVirtualComponent aComponent) {
IContainer mofRoot = aComponent.getProject();
if (mofRoot == null || !mofRoot.exists())
return false;
return mofRoot.exists(new Path(aComponent.getRootFolder().getProjectRelativePath().toString() + "//" + J2EEConstants.APPLICATION_DD_URI)); //$NON-NLS-1$
}
protected void handleOpenFailureException(OpenFailureException ex) {
org.eclipse.jem.util.logger.proxy.Logger.getLogger().logError(ex);
}
public void dispose() {
if (earArtifactEdit != null) {
earArtifactEdit.dispose();
earArtifactEdit = null;
}
}
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 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();
}
}
/**
* Gets the archive.
*
* @return Returns a Archive
*/
public Archive getArchive() {
return archive;
}
/**
* 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()) {
archive.getManifest().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) {
archive.getManifest().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) {
archive.getManifest().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 manifest) {
archive.setManifest(manifest);
getClassPathSelection(); // Ensure the selection is initialized.
fireNotification(new ClasspathModelEvent(ClasspathModelEvent.MANIFEST_CHANGED));
}
public void selectEAR(int index) {
ArchiveManifest mf = new ArchiveManifestImpl((ArchiveManifestImpl) getArchive().getManifest());
earFile.close();
selectedEARComponent = availableEARComponents[index];
initializeSelection(mf);
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 (archive != null)
mf = new ArchiveManifestImpl((ArchiveManifestImpl) getArchive().getManifest());
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)
return;
nonResourceFiles = new ArrayList(3);
nonResourceFiles.add(getComponent().getProject().getFile(ProjectUtilities.DOT_PROJECT));
nonResourceFiles.add(getComponent().getProject().getFile(ProjectUtilities.DOT_CLASSPATH));
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() {
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;
}
private void initializeSelectionForWLPs() {
classPathWLPSelection = new ClassPathSelection();
try {
IClasspathContainer container = J2EEComponentClasspathUpdater.getInstance().getWebAppLibrariesContainer(component.getProject(), true);
IClasspathEntry[] containerEntries = null != container ? container.getClasspathEntries() : null;
IPath libPath = new Path("/WEB-INF/lib"); //$NON-NLS-1$
HashSet hs = new HashSet();
hs.addAll(J2EEProjectUtilities.getAllJavaNonFlexProjects());
IProject[] utilityProjects = J2EEProjectUtilities.getAllProjectsInWorkspaceOfType(J2EEProjectUtilities.UTILITY);
hs.addAll(Arrays.asList(utilityProjects));
IProject[] ejbProjects = J2EEProjectUtilities.getAllProjectsInWorkspaceOfType(J2EEProjectUtilities.EJB);
hs.addAll(Arrays.asList(ejbProjects));
for (Iterator it = hs.iterator(); it.hasNext();) {
Object item = it.next();
IProject utilProject = null;
if (item instanceof IProject) {
utilProject = (IProject) item;
if (utilProject.getName().startsWith(".")) { //$NON-NLS-1$
continue;
}
} else if (item instanceof IVirtualComponent)
utilProject = ((IVirtualComponent) item).getProject();
boolean existingEntry = false;
if (containerEntries != null) {
for (int j = 0; j < containerEntries.length; j++) {
IClasspathEntry eachEntry = containerEntries[j];
if (eachEntry.getEntryKind() == IClasspathEntry.CPE_PROJECT && eachEntry.getPath().toString().equals("/" + utilProject.getName())) { //$NON-NLS-1$
IVirtualReference ref = component.getReference(utilProject.getName());
if (ref != null && ref.getRuntimePath().equals(libPath)) {
existingEntry = true;
}
break;
}
}
}
classPathWLPSelection.createProjectElement(utilProject, existingEntry);
classPathWLPSelection.setFilterLevel(ClassPathSelection.FILTER_NONE);
}
if (component != null && J2EEProjectUtilities.isDynamicWebProject(component.getProject())) {
IVirtualReference[] newrefs = component.getReferences();
for (int i = 0; i < newrefs.length; i++) {
IVirtualReference ref = newrefs[i];
IVirtualComponent referencedComponent = ref.getReferencedComponent();
if (referencedComponent == null)
continue;
boolean isBinary = referencedComponent.isBinary();
if (isBinary) {
String unresolvedURI = ""; //$NON-NLS-1$
try {
unresolvedURI = ModuleURIUtil.getArchiveName(URI.createURI(ModuleURIUtil.getHandleString(referencedComponent)));
} catch (UnresolveableURIException e) {
e.printStackTrace();
}
URI archiveURI = URI.createURI(unresolvedURI);
boolean alreadyInList = false;
Iterator iter = classPathWLPSelection.getClasspathElements().iterator();
while (iter.hasNext()) {
ClasspathElement tmpelement = (ClasspathElement) iter.next();
if (tmpelement.getText().equals(archiveURI.lastSegment())) {
alreadyInList = true;
break;
}
}
ClasspathElement element = null;
if (!alreadyInList) {
boolean inContainer = false;
if (containerEntries != null) {
String lastSegment = archiveURI.lastSegment();
for (int j = 0; !inContainer && j < containerEntries.length; j++) {
if (containerEntries[j].getPath().lastSegment().equals(lastSegment)) {
inContainer = true;
}
}
}
if (inContainer) {
element = classPathWLPSelection.createArchiveElement(URI.createURI(ModuleURIUtil.getHandleString(referencedComponent)), referencedComponent.getName(), archiveURI.lastSegment());
classPathWLPSelection.addClasspathElement(element, unresolvedURI);
} else {
element = classPathWLPSelection.createArchiveElement(URI.createURI(ModuleURIUtil.getHandleString(referencedComponent)), archiveURI.lastSegment(), null);
classPathWLPSelection.addClasspathElement(element, unresolvedURI);
}
}
}
} // for
}
} catch (CoreException e) {
} catch (Exception e) {
Logger.getLogger().logError(e);
}
}
public boolean isWLPModel() {
return isWLPModel;
}
public void setWLPModel(boolean isWLPModel) {
this.isWLPModel = isWLPModel;
}
}