| /****************************************************************************** |
| * Copyright (c) 2009 Red Hat |
| * 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: |
| * Rob Stryker - initial implementation |
| ******************************************************************************/ |
| package org.eclipse.jst.j2ee.internal.modulecore.util; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.jst.common.internal.modulecore.util.ArchiveManifest; |
| import org.eclipse.jst.common.internal.modulecore.util.IJavaComponentDiscerner; |
| import org.eclipse.jst.common.internal.modulecore.util.ManifestUtilities; |
| import org.eclipse.jst.j2ee.project.EarUtilities; |
| import org.eclipse.wst.common.componentcore.ComponentCore; |
| import org.eclipse.wst.common.componentcore.resources.IVirtualComponent; |
| import org.eclipse.wst.common.componentcore.resources.IVirtualFile; |
| import org.eclipse.wst.common.componentcore.resources.IVirtualFolder; |
| import org.eclipse.wst.common.componentcore.resources.IVirtualReference; |
| |
| /** |
| * This class is meant to discover possible manifest entries for a parent / child combo. |
| * This might be better implemented using flat virtual component model to make more |
| * accurate use of consumes, etc. But that can change later (as usual) |
| */ |
| public class JEEManifestDiscerner implements IJavaComponentDiscerner { |
| |
| public IProject[] findParentProjects(IProject child) { |
| return EarUtilities.getReferencingEARProjects(child); |
| } |
| |
| public IVirtualReference[] findPossibleManifestEntries( |
| IProject parentProject, IProject childProject) { |
| if( EarUtilities.isEARProject(parentProject)) { |
| ArrayList<IVirtualReference> allPossible = findAllPossibleEntries(parentProject, childProject); |
| IVirtualReference[] alreadyReferenced = findCurrentManifestEntries(parentProject, childProject, allPossible); |
| allPossible.removeAll(Arrays.asList(alreadyReferenced)); |
| return allPossible.toArray(new IVirtualReference[allPossible.size()]); |
| } |
| return new IVirtualReference[]{}; |
| } |
| |
| public IVirtualReference[] findPossibleManifestEntries( |
| IProject parentProject, IProject childProject, IVirtualReference[] currentEntries) { |
| if( EarUtilities.isEARProject(parentProject)) { |
| ArrayList<IVirtualReference> allPossible = findAllPossibleEntries(parentProject, childProject); |
| allPossible.removeAll(Arrays.asList(currentEntries)); |
| return allPossible.toArray(new IVirtualReference[allPossible.size()]); |
| } |
| return new IVirtualReference[]{}; |
| } |
| |
| |
| protected ArrayList<IVirtualReference> findAllPossibleEntries(IProject parentProject, IProject childProject) { |
| IVirtualComponent ear = ComponentCore.createComponent(parentProject); |
| IVirtualReference[] hardRefs = ear.getReferences(); |
| IVirtualReference[] actual_tmp = trimEarHardRefs(ear, childProject, hardRefs); |
| IVirtualReference[] actual_clean = cleanHardRefs(actual_tmp, childProject, hardRefs); |
| ArrayList<IVirtualReference> refs = new ArrayList<IVirtualReference>(); |
| refs.addAll(Arrays.asList(actual_clean)); |
| return refs; |
| } |
| |
| /** |
| * Prune out unacceptable reference types |
| * @param childProject |
| * @param hardRefs |
| * @return |
| */ |
| private IVirtualReference[] trimEarHardRefs(IVirtualComponent ear, IProject childProject, IVirtualReference[] hardRefs) { |
| String earLibDir = EarUtilities.getEARLibDir(ear); |
| IPath earLibDirPath = null; |
| if(earLibDir != null) |
| earLibDirPath = new Path(earLibDir).makeRelative(); |
| ArrayList<IVirtualReference> refs = new ArrayList<IVirtualReference>(); |
| // We have to prune out self-references |
| for( int i = 0; i < hardRefs.length; i++ ) { |
| // This is actually hard to make sure we're not adding ourself |
| if((hardRefs[i].getReferencedComponent().isBinary() |
| || hardRefs[i].getDependencyType() == IVirtualReference.DEPENDENCY_TYPE_CONSUMES |
| || !hardRefs[i].getReferencedComponent().getProject().equals(childProject)) |
| && hardRefs[i].getArchiveName().endsWith("jar")) { //$NON-NLS-1$ // Only jar's are legal in MANIFEST |
| if(earLibDirPath == null || earLibDirPath.isEmpty() || !hardRefs[i].getRuntimePath().makeRelative().equals(earLibDirPath)) {// Jars in the EAR's library directory should not be added to the MANIFEST for EE5/EE6 |
| refs.add(hardRefs[i]); |
| } |
| } |
| } |
| return refs.toArray(new IVirtualReference[refs.size()]); |
| } |
| |
| /** |
| * Make sure the runtime path + archiveName is what should go in the manifest file |
| * if this reference is selected |
| * |
| * @param original |
| * @return |
| */ |
| private IVirtualReference[] cleanHardRefs(IVirtualReference[] original, IProject childProject, IVirtualReference[] hardRefs) { |
| IVirtualReference childProjectVirtualRef = null; |
| for( int i = 0; i < hardRefs.length; i++ ) { |
| if(hardRefs[i].getReferencedComponent().getProject().equals(childProject)) { |
| childProjectVirtualRef = hardRefs[i]; |
| break; |
| } |
| } |
| |
| IVirtualReference[] newRefs = new IVirtualReference[original.length]; |
| for( int i = 0; i < newRefs.length; i++ ) { |
| newRefs[i] = ComponentCore.createReference(original[i].getEnclosingComponent(), |
| original[i].getReferencedComponent(), calculateManifestRelativeRuntimePath(childProjectVirtualRef, original[i])); |
| newRefs[i].setDependencyType(original[i].getDependencyType()); |
| newRefs[i].setArchiveName((new Path(original[i].getArchiveName())).lastSegment()); |
| } |
| return newRefs; |
| } |
| |
| public static IPath calculateManifestRelativeRuntimePath(IVirtualReference childProjectVirtualRef, IVirtualReference manifestEntryReference) { |
| IPath manifestEntryPath = manifestEntryReference.getRuntimePath(); |
| // Return the manifestEntryReference's relative runtime path if the child project is at root level |
| if(childProjectVirtualRef == null || childProjectVirtualRef.getRuntimePath().equals("/")) //$NON-NLS-1$ |
| return manifestEntryPath.makeRelative(); |
| IPath childProjectRuntimePath = childProjectVirtualRef.getRuntimePath(); |
| |
| // Return an empty runtime path if the child project and manifest entry have same runtime path |
| if(childProjectRuntimePath.equals(manifestEntryPath)) |
| return new Path(""); //$NON-NLS-1$ |
| |
| String[] childProjectFolders = childProjectRuntimePath.segments(); |
| String[] manifestEntryFolders = manifestEntryPath.segments(); |
| int commonFolderCount = 0; |
| for(int i = 0; i < childProjectFolders.length; i++) { |
| if(i >= manifestEntryFolders.length || !childProjectFolders[i].equals(manifestEntryFolders[i])) |
| break; |
| commonFolderCount++; |
| } |
| final String upOneLevel = "../"; //$NON-NLS-1$ |
| String resultString = ""; //$NON-NLS-1$ |
| for(int i = 0; i < childProjectFolders.length - commonFolderCount; i++) { |
| resultString += upOneLevel; |
| } |
| return new Path(resultString).append(manifestEntryPath.removeFirstSegments(commonFolderCount)); |
| } |
| |
| |
| public IVirtualReference[] findCurrentManifestEntries( |
| IProject parentProject, IProject childProject) { |
| return findCurrentManifestEntries(parentProject, childProject, |
| findAllPossibleEntries(parentProject, childProject)); |
| } |
| |
| protected IVirtualReference[] findCurrentManifestEntries( |
| IProject parentProject, IProject childProject, ArrayList<IVirtualReference> allPossibleEntries) { |
| |
| ArrayList<IVirtualReference> currentEntries = new ArrayList<IVirtualReference>(); |
| |
| IFile manifestFile = getManifestFile(childProject); |
| if(manifestFile != null) { |
| ArchiveManifest manifest = ManifestUtilities.getManifest(manifestFile); |
| List<String> entries = Arrays.asList(manifest.getClassPathTokenized()); |
| Iterator<IVirtualReference> i = allPossibleEntries.iterator(); |
| IVirtualReference currentI; |
| |
| // Add entries that are in the Manifest |
| while(i.hasNext()) { |
| currentI = i.next(); |
| String currentEntry = currentI.getRuntimePath().append((new Path(currentI.getArchiveName())).lastSegment()).toString(); |
| if(entries.contains(currentEntry)) |
| currentEntries.add(currentI); |
| } |
| } |
| return currentEntries.toArray(new IVirtualReference[currentEntries.size()]); |
| } |
| |
| protected IFile getManifestFile(IProject child) { |
| IVirtualComponent root = ComponentCore.createComponent(child); |
| IVirtualFolder rootFolder = root.getRootFolder(); |
| IVirtualFile vf = rootFolder.getFile(new Path("META-INF/MANIFEST.MF")); //$NON-NLS-1$ |
| if( vf.exists() ) |
| return vf.getUnderlyingFile(); |
| return null; |
| } |
| |
| /** |
| * This is the usecase we'd like to deprecate, one day. One day..... |
| * (Though konstantin says NO) |
| * @param parentProject |
| * @param hardRefs |
| * @return |
| */ |
| // private IVirtualReference[] LEGACY_getClasspathDependencies(IProject parentProject, IVirtualReference[] hardRefs) { |
| // ArrayList<IVirtualReference> retval = new ArrayList<IVirtualReference>(); |
| // ArrayList<IProject> seenProjects = new ArrayList<IProject>(); |
| // seenProjects.add(parentProject); |
| // for( int i = 0; i < hardRefs.length; i++ ) { |
| // if( hardRefs[i].getReferencedComponent() instanceof IClasspathDependencyProvider) { |
| // // Already flagged classpaths |
| // final IClasspathDependencyProvider j2eeComp = (IClasspathDependencyProvider) hardRefs[i].getReferencedComponent(); |
| // final IVirtualReference[] refs = j2eeComp.getJavaClasspathReferences(); |
| // for( int j = 0; j < refs.length; j++ ) { |
| // if( !((IClasspathDependencyComponent)refs[j].getReferencedComponent()).isClassFolder()) { |
| // // Clean this reference's runtime path |
| // IPath newRuntimePath = refs[j].getRuntimePath(); |
| // if( newRuntimePath.toString().startsWith("../")) //$NON-NLS-1$ |
| // newRuntimePath = new Path(newRuntimePath.toString().substring(2)).makeRelative(); |
| // IVirtualReference tmp = ComponentCore.createReference(refs[j].getEnclosingComponent(), |
| // refs[j].getReferencedComponent(), newRuntimePath); |
| // tmp.setDependencyType(refs[j].getDependencyType()); |
| // tmp.setArchiveName(refs[j].getArchiveName()); |
| // retval.add(tmp); |
| // } |
| // } |
| // } |
| // } |
| // return retval.toArray(new IVirtualReference[retval.size()]); |
| // } |
| // // Now find *potential* entries |
| // IProject cp = hardRefs[i].getReferencedComponent().getProject(); |
| // if( !seenProjects.contains(cp)) { |
| // seenProjects.add(cp); |
| // IJavaProjectLite lite = JavaCoreLite.create(cp); |
| // try { |
| // List<IClasspathEntry> entries = ClasspathDependencyUtil.getPotentialComponentClasspathDependencies(lite); |
| // Iterator<IClasspathEntry> k = entries.iterator(); |
| // while(k.hasNext()) { |
| // IVirtualReference tmp = LEGACY_convertClasspathEntry(cp, k.next()); |
| // if( tmp != null ) |
| // retval.add(tmp); |
| // } |
| // } catch( CoreException ce ) {} |
| // } |
| // } |
| |
| |
| // |
| // private IVirtualReference LEGACY_convertClasspathEntry(IProject project, IClasspathEntry entry) { |
| // IVirtualComponent tmp = ComponentCore.createComponent(project); |
| // final IPath entryLocation = ClasspathDependencyUtil.getEntryLocation(entry); |
| // if(entryLocation != null && !ClasspathDependencyUtil.isClassFolderEntry(entry)) { |
| // final IClasspathAttribute attrib = ClasspathDependencyUtil.checkForComponentDependencyAttribute( |
| // entry, DependencyAttributeType.CLASSPATH_COMPONENT_DEPENDENCY, false); |
| // boolean isWebApp = J2EEProjectUtilities.isDynamicWebProject(project); |
| // IPath runtimePath = ClasspathDependencyUtil.getRuntimePath(attrib, isWebApp, false); |
| // String componentPath = VirtualArchiveComponent.CLASSPATHARCHIVETYPE |
| // + IPath.SEPARATOR + entryLocation.toPortableString(); |
| // IVirtualComponent entryComponent = new ClasspathDependencyVirtualComponent( |
| // project, componentPath, false); |
| // final IVirtualReference entryReference = ComponentCore.createReference(tmp, entryComponent, runtimePath); |
| // ((VirtualReference) entryReference).setDerived(true); |
| // entryReference.setArchiveName(ClasspathDependencyUtil.getArchiveName(entry)); |
| // return entryReference; |
| // } |
| // return null; |
| // } |
| |
| } |