blob: 00b571bef51b8269915c6e2c57c15760b4125e73 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006 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:
* Justin Chen - development check in
*******************************************************************************/
package org.eclipse.jst.jsf.core.internal.jsflibraryconfig;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.jar.Manifest;
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.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jem.workbench.utility.JemProjectUtilities;
import org.eclipse.jface.operation.IRunnableWithProgress;
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.helpers.ArchiveManifest;
import org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.ArchiveManifestImpl;
import org.eclipse.jst.j2ee.internal.J2EEConstants;
import org.eclipse.jst.j2ee.internal.common.ClasspathModel;
import org.eclipse.jst.j2ee.internal.common.operations.UpdateJavaBuildPathOperation;
import org.eclipse.jst.jsf.core.internal.JSFCorePlugin;
import org.eclipse.jst.jsf.core.internal.Messages;
import org.eclipse.jst.jsf.core.internal.jsflibraryregistry.ArchiveFile;
import org.eclipse.jst.jsf.core.internal.jsflibraryregistry.JSFLibrary;
import org.eclipse.jst.jsf.core.internal.project.facet.JSFUtils;
import org.eclipse.osgi.util.NLS;
import org.eclipse.wst.common.componentcore.ComponentCore;
import org.eclipse.wst.common.componentcore.internal.impl.ModuleURIUtil;
import org.eclipse.wst.common.componentcore.internal.resources.VirtualArchiveComponent;
import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
import org.eclipse.wst.common.componentcore.resources.IVirtualReference;
import org.eclipse.wst.common.frameworks.internal.ui.WTPUIPlugin;
/**
* The <b>J2EEModuleDependencyDelegate</b> provide services to update
* J2EE module dependencies and java build path if JSF libraries
* are referenced in a web application.
*
* @author Justin Chen - Oracle
*
*/
public class J2EEModuleDependencyDelegate {
private IProject project = null;
private ClasspathModel model = null;
/**
* @param project
*/
public J2EEModuleDependencyDelegate(IProject project) {
this.project = project;
this.model = newClasspathModel(project);
}
/**
* Add given <b>jsfLibrary</b> as project dependency.
* If <b>toDeploy</b> flag is true, the JSF library JARs will be
* added as J2EE module dependencies.
* Otherwise, JARs are added in project build path only.
*
* @param jsfLibrary
* @param toDeploy
* @param monitor
*/
public void addProjectDependency(JSFLibrary jsfLibrary, boolean toDeploy, IProgressMonitor monitor) {
IPath[] jarPaths = JSFUtils.getJARPathforJSFLibwFilterMissingJars(jsfLibrary, true);
this.updateProjectDependency(jarPaths, toDeploy, monitor);
}
/**
* Remove given <b>jsfLibrary</b> from project dependency.
*
* @param jsfLibrary
* @param monitor
*/
public void removeProjectDependency(JSFLibrary jsfLibrary, IProgressMonitor monitor) {
IPath[] elements = JSFUtils.getJARPathforJSFLib(jsfLibrary, false);
this.removeProjectDependency_(elements, monitor);
}
/**
* @param jsfLibrary
* @param monitor
*
public void addLibraryToBuildPath(JSFLibraryDecorator jsfLibrary, IProgressMonitor monitor) {
IPath[] elements = JSFUtils.getJARPathforJSFLib(jsfLibrary.getLibrary());
this.updateProjectDependency(elements, false, monitor);
}
*/
/**
* To update J2EE Module dependencies from given collection of JARs and deployment flag.
*
* @param elems
* @param deployme
* @param monitor
*/
private void updateProjectDependency(IPath[] elems, boolean deployme, IProgressMonitor monitor) {
ClassPathSelection selection = null;
/**
* For each JAR defined in a JSF Library, it is added as J2EE Module Dependency if
* the JSF Library is checked for deployment. However, JARs are added into project build path
* regardless if a JSF Library is checked for deployment or not.
*
*/
String type = VirtualArchiveComponent.LIBARCHIVETYPE + IPath.SEPARATOR;
for (int i= 0; i < elems.length; i++) {
IVirtualComponent archive = ComponentCore.createArchiveComponent( model.getComponent().getProject(), type + elems[i].toString());
// Added as J2EE Module Dependency if need to be deployed
if (deployme) {
ArrayList vlist = new ArrayList(Collections.EMPTY_LIST);
IVirtualReference[] oldrefs = model.getComponent().getReferences();
for (int j = 0; j < oldrefs.length; j++) {
IVirtualReference ref = oldrefs[j];
vlist.add(ref);
}
IVirtualReference ref = ComponentCore.createReference(
model.getComponent(),
archive,
new Path("/WEB-INF/lib") ); //$NON-NLS-1$
addReferences(vlist, ref);
IVirtualReference[] refs = new IVirtualReference[vlist.size()];
for (int j = 0; j < vlist.size(); j++) {
IVirtualReference tmpref = (IVirtualReference) vlist.get(j);
refs[j] = tmpref;
}
model.getComponent().setReferences(refs);
} else {
// added into the path selection to update build path later.
ClasspathElement element = createClassPathElement(archive, archive.getName(), true);
if (selection == null) {
selection = createClassPathSelectionForExternalJar(element);
} else {
selection.getClasspathElements().add(element);
}
model.getClassPathSelectionForWLPs().getClasspathElements().add(element);
}
} // end For
// Add JARs into build path for selected JSF libs checked for not deploy.
if (selection != null) {
IRunnableWithProgress buildPathOP = createBuildPathOperationForExternalJar(selection);
try {
buildPathOP.run(monitor);
} catch (InvocationTargetException e) {
JSFCorePlugin.getDefault().getMsgLogger().log(e);
} catch (InterruptedException e) {
JSFCorePlugin.getDefault().getMsgLogger().log(e);
}
}
}
/**
* To remove given collection of JARs from project's J2EE Module Dependencies.
*
* @param elems
* @param monitor
*/
private void removeProjectDependency_(IPath[] elems, IProgressMonitor monitor) {
ClassPathSelection selection = null;
for (int i= 0; i < elems.length; i++) {
String type = VirtualArchiveComponent.LIBARCHIVETYPE + IPath.SEPARATOR;
IVirtualComponent archive = ComponentCore.createArchiveComponent( model.getComponent().getProject(), type + elems[i].toString());
ArrayList vlist = new ArrayList(Collections.EMPTY_LIST);
IVirtualReference[] oldrefs = model.getComponent().getReferences();
for (int j = 0; j < oldrefs.length; j++) {
IVirtualReference ref = oldrefs[j];
vlist.add(ref);
}
// Remove the reference
IVirtualReference ref = ComponentCore.createReference(
model.getComponent(),
archive,
new Path("/WEB-INF/lib") ); //$NON-NLS-1$
removeReference(vlist, ref);
IVirtualReference[] refs = new IVirtualReference[vlist.size()];
for (int j = 0; j < vlist.size(); j++) {
IVirtualReference tmpref = (IVirtualReference) vlist.get(j);
refs[j] = tmpref;
}
model.getComponent().setReferences(refs);
// Update project classpath
ClasspathElement element = createClassPathElement(archive, archive.getName(), false);
if (selection == null) {
selection = createClassPathSelectionForExternalJar(element);
} else {
selection.getClasspathElements().add(element);
}
selection.getClasspathElements().add(element);
model.getClassPathSelectionForWLPs().getClasspathElements().remove(element);
} // end for
IRunnableWithProgress buildPathOP = createBuildPathOperationForExternalJar(selection);
try {
buildPathOP.run(monitor);
} catch (InvocationTargetException e) {
JSFCorePlugin.getDefault().getMsgLogger().log(e);
} catch (InterruptedException e) {
JSFCorePlugin.getDefault().getMsgLogger().log(e);
}
}
private void removeReference(ArrayList vList, IVirtualReference ref) {
IVirtualReference elem = null;
for (int i = 0; i < vList.size(); i++) {
elem = (IVirtualReference)vList.get(i);
if (elem.getReferencedComponent().getName().equalsIgnoreCase(ref.getReferencedComponent().getName())) {
vList.remove(elem);
}
}
}
/**
* Check if archive component already exists
* But, how to tell if two references are equal?
*
* @param vlist
* @param ref
*/
private void addReferences(ArrayList vlist, IVirtualReference ref) {
IVirtualReference elem = null;
boolean exist = false;
for (int i = 0; i < vlist.size(); i++) {
elem = (IVirtualReference)vlist.get(i);
if (elem.getReferencedComponent().getName().equalsIgnoreCase(ref.getReferencedComponent().getName())) {
exist = true;
break;
}
}
if ( !exist) {
vlist.add(ref);
}
}
private ClasspathModel newClasspathModel(IProject project) {
ClasspathModel model = new ClasspathModel(null);
model.setProject(project);
if( model.getComponent() != null ){
updateModelManifest(model);
}
return model;
}
private ClasspathElement createClassPathElement(
IVirtualComponent archiveComp,
String unresolvedName,
boolean addedToPath) {
URI uri = URI.createURI(ModuleURIUtil.getHandleString(archiveComp));
ClasspathElement element = new ClasspathElement(uri);
element.setValid(false);
element.setSelected(addedToPath);
element.setRelativeText(unresolvedName);
element.setText(unresolvedName);
element.setEarProject(null);
return element;
}
private ClassPathSelection createClassPathSelectionForExternalJar(ClasspathElement element){
ClassPathSelection selection = new ClassPathSelection();
selection.getClasspathElements().add(element);
return selection;
}
private IRunnableWithProgress createBuildPathOperationForExternalJar(ClassPathSelection selection) {
IJavaProject javaProject = JemProjectUtilities.getJavaProject(project);
return WTPUIPlugin.getRunnableWithProgress(new UpdateJavaBuildPathOperation(javaProject, selection));
}
private void updateModelManifest(ClasspathModel model) {
if (JemProjectUtilities.isBinaryProject(project) || model.getAvailableEARComponents().length == 0)
return;
IContainer root = null;
IFile manifestFile = null;
if (project != null) {
root = project;
} else {
root = JemProjectUtilities.getSourceFolderOrFirst(project, null);
}
if (root != null) {
manifestFile = root.getFile(new Path(J2EEConstants.MANIFEST_URI));
}
if (manifestFile == null || !manifestFile.exists())
return;
InputStream in = null;
try {
in = manifestFile.getContents();
ArchiveManifest mf = new ArchiveManifestImpl(new Manifest(in));
model.primSetManifest(mf);
} catch (CoreException e) {
model.primSetManifest(new ArchiveManifestImpl());
} catch (IOException iox) {
model.primSetManifest(new ArchiveManifestImpl());
} finally {
if (in != null) {
try {
in.close();
} catch (IOException weTried) {
//Ignore
}
}
}
}
}