/******************************************************************************* * Copyright (c) 2003, 2011 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.componentcore.util; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.jdt.core.IClasspathAttribute; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jst.common.internal.modulecore.IClasspathDependencyComponent; import org.eclipse.jst.common.internal.modulecore.IClasspathDependencyReceiver; import org.eclipse.jst.common.jdt.internal.javalite.JavaCoreLite; import org.eclipse.jst.j2ee.classpathdep.ClasspathDependencyUtil; import org.eclipse.jst.j2ee.classpathdep.IClasspathDependencyConstants.DependencyAttributeType; import org.eclipse.jst.j2ee.componentcore.J2EEModuleVirtualArchiveComponent; import org.eclipse.jst.j2ee.componentcore.J2EEModuleVirtualComponent; import org.eclipse.jst.j2ee.internal.common.J2EEDependencyListener; import org.eclipse.jst.j2ee.internal.common.classpath.J2EEComponentClasspathInitializer; import org.eclipse.jst.j2ee.internal.common.classpath.J2EEComponentClasspathUpdater; import org.eclipse.jst.j2ee.internal.plugin.IJ2EEModuleConstants; import org.eclipse.jst.j2ee.internal.plugin.J2EEPlugin; import org.eclipse.jst.j2ee.project.JavaEEProjectUtilities; import org.eclipse.wst.common.componentcore.ComponentCore; import org.eclipse.wst.common.componentcore.ModuleCoreNature; import org.eclipse.wst.common.componentcore.internal.ReferencedComponent; import org.eclipse.wst.common.componentcore.internal.builder.IDependencyGraph; import org.eclipse.wst.common.componentcore.internal.resources.VirtualArchiveComponent; import org.eclipse.wst.common.componentcore.internal.resources.VirtualComponent; import org.eclipse.wst.common.componentcore.internal.resources.VirtualFolder; import org.eclipse.wst.common.componentcore.internal.resources.VirtualReference; import org.eclipse.wst.common.componentcore.internal.util.IComponentImplFactory; import org.eclipse.wst.common.componentcore.internal.util.VirtualReferenceUtilities; 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; import org.eclipse.wst.common.componentcore.resources.IVirtualResource; public class EARVirtualComponent extends VirtualComponent implements IComponentImplFactory, IClasspathDependencyReceiver { public static String [] EXTENSIONS_TO_IGNORE = new String [] {IJ2EEModuleConstants.JAR_EXT, ".zip", IJ2EEModuleConstants.RAR_EXT, IJ2EEModuleConstants.WAR_EXT }; //$NON-NLS-1$ private IVirtualReference[] cachedReferences; private long depGraphModStamp; private long jeeModStamp; public EARVirtualComponent() { super(); } public EARVirtualComponent(IProject aProject, IPath aRuntimePath) { super(aProject, aRuntimePath); } public IVirtualComponent createArchiveComponent(IProject aProject, String archiveLocation, IPath aRuntimePath) { return new J2EEModuleVirtualArchiveComponent(aProject, archiveLocation, aRuntimePath); } public IVirtualComponent createComponent(IProject aProject) { return new EARVirtualComponent(aProject, new Path("/")); //$NON-NLS-1$ } public IVirtualFolder createFolder(IProject aProject, IPath aRuntimePath) { return new VirtualFolder(aProject, aRuntimePath); } @Override protected boolean shouldCacheReferences() { return true; } private List<IVirtualReference> getHardReferences(IVirtualComponent earComponent) { IVirtualReference[] comparison = super.getReferences(new HashMap<String, Object>()); ArrayList<IVirtualReference> refs2 = new ArrayList<IVirtualReference>(); refs2.addAll(Arrays.asList(comparison)); return refs2; } @Override protected void customizeCreatedReference(IVirtualReference reference, Object referenceComponent) { if( referenceComponent instanceof ReferencedComponent ) { if (((ReferencedComponent) referenceComponent).getArchiveName() != null) { reference.setArchiveName(((ReferencedComponent) referenceComponent).getArchiveName()); } else { reference.setArchiveName(VirtualReferenceUtilities.INSTANCE.getDefaultArchiveName(reference)); } }else { VirtualReferenceUtilities.INSTANCE.ensureReferencesHaveNames(new IVirtualReference[]{reference}); } } /** * Returns the resulting list of referenced components based off the hard references and archives mapping to the root folder. * * @param earComponent * @param hardReferences * @param membersToIgnore * @return */ private static List getLooseArchiveReferences(EARVirtualComponent earComponent, List hardReferences) { return getLooseArchiveReferences(earComponent, hardReferences, null, earComponent.getRootFolder()); } private static List getLooseArchiveReferences(EARVirtualComponent earComponent, List hardReferences, List dynamicReferences, IVirtualFolder folder) { Map<EARVirtualComponent, List> cache = J2EEComponentClasspathInitializer.getLooseConfigCache(); if (cache != null) { List list = cache.get(earComponent); if (list != null) { return list; } } List list = getLooseArchiveReferences2(earComponent, hardReferences, null, folder); if (cache != null) { cache.put(earComponent, list); } return list; } private static List getLooseArchiveReferences2(EARVirtualComponent earComponent, List hardReferences, List dynamicReferences, IVirtualFolder folder) { List innerDynamicReferences = dynamicReferences; try { IVirtualResource[] members = folder.members(); for (int i = 0; i < members.length; i++) { if (IVirtualResource.FILE == members[i].getType()) { if(isDynamicComponent((IVirtualFile)members[i])){ IPath archiveFullPath = new Path(members[i].getRuntimePath().toString()); boolean shouldInclude = true; for (int j = 0; j < hardReferences.size() && shouldInclude; j++) { IVirtualReference tmpRef = ((IVirtualReference) hardReferences.get(j)); IPath tmpFullPath = tmpRef.getRuntimePath().append(tmpRef.getArchiveName()); if( tmpFullPath.equals(archiveFullPath)) shouldInclude = false; } if (shouldInclude) { IResource iResource = members[i].getUnderlyingResource(); IVirtualComponent dynamicComponent = ComponentCore.createArchiveComponent(earComponent.getProject(), VirtualArchiveComponent.LIBARCHIVETYPE + iResource.getFullPath().toString()); IVirtualReference dynamicRef = ComponentCore.createReference(earComponent, dynamicComponent); ((VirtualReference)dynamicRef).setDerived(true); dynamicRef.setArchiveName(archiveFullPath.lastSegment()); dynamicRef.setRuntimePath(archiveFullPath.removeLastSegments(1)); if (null == innerDynamicReferences) { innerDynamicReferences = new ArrayList(); } innerDynamicReferences.add(dynamicRef); } } } else if(IVirtualResource.FOLDER == members[i].getType()){ innerDynamicReferences = getLooseArchiveReferences2(earComponent, hardReferences, innerDynamicReferences, (IVirtualFolder)members[i]); } } } catch (CoreException e) { J2EEPlugin.logError(e); } return innerDynamicReferences; } public static boolean isDynamicComponent(IVirtualFile vFile){ String archiveName = vFile.getName(); for(int j = 0; j<EXTENSIONS_TO_IGNORE.length; j++){ if(J2EEComponentClasspathUpdater.endsWithIgnoreCase(archiveName, EXTENSIONS_TO_IGNORE[j])){ return true; } } return false; } @Override public IVirtualReference[] getReferences() { IVirtualReference[] cached = getCachedReferences(); if (cached != null) return cached; List hardReferences = getHardReferences(this); List dynamicReferences = getLooseArchiveReferences(this, hardReferences); if (dynamicReferences != null) { hardReferences.addAll(dynamicReferences); } cachedReferences = (IVirtualReference[]) hardReferences.toArray(new IVirtualReference[hardReferences.size()]); return cachedReferences; } @Override public IVirtualReference[] getReferences(Map<String, Object> options) { Object refType = options.get(IVirtualComponent.REQUESTED_REFERENCE_TYPE); if( refType != null && (IVirtualComponent.NON_DERIVED_REFERENCES.equals(refType) || IVirtualComponent.HARD_REFERENCES.equals(refType) || IVirtualComponent.DISPLAYABLE_REFERENCES.equals(refType))) { List<IVirtualReference> hardReferences = getHardReferences(this); return hardReferences.toArray(new IVirtualReference[hardReferences.size()]); } if( refType != null && IVirtualComponent.DISPLAYABLE_REFERENCES_ALL.equals(refType)){ checkIfStillValid(); // This will clear the cache of raw references if needed. return getAllReferences(); } IVirtualReference[] refs = getReferences(); Boolean objGetExpandRefs = (Boolean)options.get(J2EEModuleVirtualComponent.GET_EXPANDED_LIB_REFS); boolean getExpandRefs = objGetExpandRefs != null ? objGetExpandRefs.booleanValue() : false; if (getExpandRefs) { return JavaEEProjectUtilities.getExpandedReferences(this, refs); } return refs; } protected boolean shouldAddClasspathDependencyDerivedReference() { IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); for( int i = 0; i < projects.length; i++ ) { try { if( projects[i].hasNature(JavaCoreLite.NATURE_ID) && ModuleCoreNature.isFlexibleProject(projects[i])) { Map <IClasspathEntry, IClasspathAttribute> results = ClasspathDependencyUtil.getRawComponentClasspathDependencies( JavaCoreLite.create(projects[i]), DependencyAttributeType.CLASSPATH_COMPONENT_DEPENDENCY); if( !results.isEmpty()) return true; } } catch(CoreException ce) { } } return false; } // Returns cache if still valid or null public IVirtualReference[] getCachedReferences() { if (cachedReferences != null && checkIfStillValid()) return cachedReferences; return null; } private boolean checkIfStillValid() { boolean valid = IDependencyGraph.INSTANCE.getModStamp() == depGraphModStamp; valid = valid && J2EEDependencyListener.INSTANCE.getModStamp() == jeeModStamp; if (!valid) { clearCache(); } return valid; } @Override protected void clearCache() { super.clearCache(); depGraphModStamp = IDependencyGraph.INSTANCE.getModStamp(); jeeModStamp = J2EEDependencyListener.INSTANCE.getModStamp(); cachedReferences = null; } public boolean canReceiveClasspathDependencies() { return true; } public IPath getClasspathFolderPath(IClasspathDependencyComponent component) { return Path.EMPTY; } }