| package org.eclipse.jst.j2ee.internal.componentcore; |
| |
| import java.io.IOException; |
| import java.util.HashSet; |
| import java.util.Hashtable; |
| import java.util.Iterator; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.zip.ZipException; |
| |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.jst.j2ee.internal.J2EEConstants; |
| import org.eclipse.jst.j2ee.internal.archive.JavaEEArchiveUtilities; |
| import org.eclipse.jst.j2ee.internal.plugin.J2EEPlugin; |
| import org.eclipse.jst.jee.archive.ArchiveModelLoadException; |
| import org.eclipse.jst.jee.archive.ArchiveOpenFailureException; |
| import org.eclipse.jst.jee.archive.ArchiveOptions; |
| import org.eclipse.jst.jee.archive.IArchive; |
| import org.eclipse.jst.jee.archive.IArchiveFactory; |
| import org.eclipse.jst.jee.util.internal.JavaEEQuickPeek; |
| import org.eclipse.wst.common.componentcore.internal.BinaryComponentHelper; |
| import org.eclipse.wst.common.componentcore.resources.IVirtualComponent; |
| import org.eclipse.wst.common.componentcore.resources.IVirtualReference; |
| |
| public class JavaEEBinaryComponentHelper extends BinaryComponentHelper { |
| |
| private IArchive archive; |
| |
| private int localArchiveAccessCount = 0; |
| |
| public static JavaEEQuickPeek getJavaEEQuickPeek(IVirtualComponent aBinaryComponent) { |
| JavaEEBinaryComponentHelper helper = null; |
| try { |
| helper = new JavaEEBinaryComponentHelper(aBinaryComponent); |
| IArchive archive = helper.getArchive(); |
| if(archive == null){ |
| return new JavaEEQuickPeek(null); |
| } |
| JavaEEQuickPeek qp = JavaEEArchiveUtilities.INSTANCE.getJavaEEQuickPeek(archive); |
| return qp; |
| } finally { |
| if (helper != null) { |
| helper.dispose(); |
| } |
| } |
| } |
| |
| public JavaEEBinaryComponentHelper(IVirtualComponent aBinaryComponent) { |
| super(aBinaryComponent); |
| } |
| |
| @Override |
| public EObject getPrimaryRootObject() { |
| JavaEEQuickPeek qp = JavaEEArchiveUtilities.INSTANCE.getJavaEEQuickPeek(getArchive()); |
| IPath ddPath = null; |
| switch (qp.getType()) { |
| case JavaEEQuickPeek.APPLICATION_CLIENT_TYPE: |
| ddPath = new Path(J2EEConstants.APP_CLIENT_DD_URI); |
| break; |
| case JavaEEQuickPeek.EJB_TYPE: |
| ddPath = new Path(J2EEConstants.EJBJAR_DD_URI); |
| break; |
| case JavaEEQuickPeek.WEB_TYPE: |
| ddPath = new Path(J2EEConstants.WEBAPP_DD_URI); |
| break; |
| case JavaEEQuickPeek.CONNECTOR_TYPE: |
| ddPath = new Path(J2EEConstants.RAR_DD_URI); |
| break; |
| } |
| if (ddPath != null) { |
| try { |
| return (EObject) getArchive().getModelObject(ddPath); |
| } catch (ArchiveModelLoadException e) { |
| J2EEPlugin.logError(e); |
| } |
| } |
| return null; |
| } |
| |
| @Override |
| public Resource getResource(URI uri) { |
| IPath path = new Path(uri.toString()); |
| try { |
| return (Resource) ((JavaEEBinaryComponentLoadAdapter) getArchive().getLoadAdapter()).getModelObject(path); |
| } catch (ArchiveModelLoadException e) { |
| J2EEPlugin.logError(e); |
| } |
| return null; |
| } |
| |
| public IArchive accessArchive() { |
| IArchive archive = getArchive(); |
| if (null != archive) { |
| ArchiveCache cache = ArchiveCache.getInstance(); |
| cache.accessArchive(archive); |
| synchronized (this) { |
| localArchiveAccessCount++; |
| } |
| } |
| return archive; |
| } |
| |
| public void releaseArchive(IArchive archive) { |
| if (archive != this.archive) { |
| throw new RuntimeException("The IArchive parameter must be the same IArchive retrieved from accessArchive"); |
| } |
| if (null != archive) { |
| ArchiveCache cache = ArchiveCache.getInstance(); |
| cache.releaseArchive(archive); |
| synchronized (this) { |
| localArchiveAccessCount--; |
| } |
| } |
| } |
| |
| @Override |
| public void dispose() { |
| super.dispose(); |
| int count = 0; |
| synchronized (this) { |
| count = localArchiveAccessCount; |
| } |
| if (count > 0 && archive != null) { |
| ArchiveCache cache = ArchiveCache.getInstance(); |
| for (int i = 0; i < count; i++) { |
| cache.releaseArchive(archive); |
| synchronized (this) { |
| localArchiveAccessCount--; |
| } |
| } |
| } |
| } |
| |
| protected IArchive getArchive() { |
| if (archive == null) { |
| archive = getUniqueArchive(); |
| } |
| return archive; |
| } |
| |
| protected IArchive getUniqueArchive() { |
| try { |
| return openArchive(); |
| } catch (ArchiveOpenFailureException e) { |
| J2EEPlugin.logError(e); |
| } |
| return null; |
| } |
| |
| protected IArchive openArchive() throws ArchiveOpenFailureException { |
| ArchiveCache cache = ArchiveCache.getInstance(); |
| IArchive archive = cache.getArchive(getComponent()); |
| if (archive == null) { |
| archive = cache.openArchive(this); |
| } |
| if (archive != null) { |
| cache.accessArchive(archive); |
| synchronized (this) { |
| localArchiveAccessCount++; |
| } |
| } |
| return archive; |
| } |
| |
| public static void clearDisconnectedArchivesInEAR(IVirtualComponent earComponent) { |
| ArchiveCache.getInstance().clearDisconnectedArchivesInEAR(earComponent); |
| } |
| |
| public static void clearAllArchivesInProject(IProject earProject) { |
| ArchiveCache.getInstance().clearAllArchivesInProject(earProject); |
| } |
| |
| /** |
| * This cache manages IArchives across all |
| * {@link JavaEEBinaryComponentHelper} instances. If multiple |
| * {@link JavaEEBinaryComponentHelper} instances exist for the same |
| * underlying archive file (e.g. a jar file on disk) all will use the exact |
| * same IArchive instance. Care needs to be taken in managing the opening |
| * and closing of this IArchive which should only be done through internal |
| * methods within {@link JavaEEBinaryComponentHelper} |
| */ |
| private static class ArchiveCache { |
| |
| private static ArchiveCache instance = null; |
| |
| public static ArchiveCache getInstance() { |
| if (instance == null) { |
| instance = new ArchiveCache(); |
| } |
| return instance; |
| } |
| |
| protected Map<IVirtualComponent, IArchive> componentsToArchives = new Hashtable<IVirtualComponent, IArchive>(); |
| |
| protected Map<IArchive, Integer> archiveAccessCount = new Hashtable<IArchive, Integer>(); |
| |
| public synchronized void accessArchive(IArchive archive) { |
| Integer count = archiveAccessCount.get(archive); |
| Integer newCount = new Integer(count.intValue() + 1); |
| archiveAccessCount.put(archive, newCount); |
| if (newCount.intValue() == 1) { |
| JavaEEBinaryComponentLoadAdapter binaryAdapter = null; |
| if (archive.getArchiveOptions().hasOption(JavaEEArchiveUtilities.WRAPPED_LOAD_ADAPTER)) { |
| binaryAdapter = (JavaEEBinaryComponentLoadAdapter) archive.getArchiveOptions().getOption(JavaEEArchiveUtilities.WRAPPED_LOAD_ADAPTER); |
| } else { |
| binaryAdapter = (JavaEEBinaryComponentLoadAdapter) archive.getArchiveOptions().getOption(ArchiveOptions.LOAD_ADAPTER); |
| } |
| if (!binaryAdapter.isPhysicallyOpen()) { |
| try { |
| binaryAdapter.physicallyOpen(); |
| } catch (ZipException e) { |
| org.eclipse.jst.j2ee.internal.plugin.J2EEPlugin.logError(e); |
| } catch (IOException e) { |
| org.eclipse.jst.j2ee.internal.plugin.J2EEPlugin.logError(e); |
| } |
| } |
| } |
| } |
| |
| public synchronized void releaseArchive(IArchive archive) { |
| Integer count = archiveAccessCount.get(archive); |
| Integer newCount = new Integer(count.intValue() - 1); |
| archiveAccessCount.put(archive, newCount); |
| if (newCount.intValue() == 0) { |
| JavaEEBinaryComponentLoadAdapter binaryAdapter = null; |
| if (archive.getArchiveOptions().hasOption(JavaEEArchiveUtilities.WRAPPED_LOAD_ADAPTER)) { |
| binaryAdapter = (JavaEEBinaryComponentLoadAdapter) archive.getArchiveOptions().getOption(JavaEEArchiveUtilities.WRAPPED_LOAD_ADAPTER); |
| } else { |
| binaryAdapter = (JavaEEBinaryComponentLoadAdapter) archive.getArchiveOptions().getOption(ArchiveOptions.LOAD_ADAPTER); |
| } |
| if (binaryAdapter.isPhysicallyOpen()) { |
| binaryAdapter.physicallyClose(); |
| } |
| } |
| } |
| |
| public synchronized IArchive getArchive(IVirtualComponent component) { |
| IArchive archive = componentsToArchives.get(component); |
| return archive; |
| } |
| |
| public synchronized void clearDisconnectedArchivesInEAR(IVirtualComponent earComponent) { |
| if (componentsToArchives.isEmpty()) { |
| return; |
| } |
| Set<IVirtualComponent> liveBinaryComponnts = new HashSet<IVirtualComponent>(); |
| IVirtualReference[] refs = earComponent.getReferences(); |
| IVirtualComponent component = null; |
| for (int i = 0; i < refs.length; i++) { |
| component = refs[i].getReferencedComponent(); |
| if (component.isBinary()) { |
| liveBinaryComponnts.add(component); |
| } |
| } |
| clearArchivesInProject(earComponent.getProject(), liveBinaryComponnts); |
| } |
| |
| public synchronized void clearAllArchivesInProject(IProject earProject) { |
| if (componentsToArchives.isEmpty()) { |
| return; |
| } |
| clearArchivesInProject(earProject, null); |
| } |
| |
| private void clearArchivesInProject(IProject earProject, Set excludeSet) { |
| Iterator iterator = componentsToArchives.entrySet().iterator(); |
| IVirtualComponent component = null; |
| IArchive archive = null; |
| while (iterator.hasNext()) { |
| Map.Entry entry = (Map.Entry) iterator.next(); |
| component = (IVirtualComponent) entry.getKey(); |
| if (component.getProject().equals(earProject) && (excludeSet == null || !excludeSet.contains(component))) { |
| archive = (IArchive) entry.getValue(); |
| IArchiveFactory.INSTANCE.closeArchive(archive); |
| iterator.remove(); |
| archiveAccessCount.remove(archive); |
| } |
| } |
| } |
| |
| public synchronized IArchive openArchive(JavaEEBinaryComponentHelper helper) throws ArchiveOpenFailureException { |
| IArchive archive = JavaEEArchiveUtilities.INSTANCE.openArchive(helper.getComponent()); |
| componentsToArchives.put(helper.getComponent(), archive); |
| archiveAccessCount.put(archive, new Integer(0)); |
| return archive; |
| } |
| } |
| |
| } |