org.eclipse.jst.j2ee.internal.archive.ConnectorComponentArchiveLoadAdapter.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.jst.j2ee.internal.archive.ConnectorComponentArchiveLoadAdapter.java

Source

/*******************************************************************************
 * Copyright (c) 2003, 2007 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.archive;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
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.IJavaProject;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jst.j2ee.internal.J2EEConstants;
import org.eclipse.jst.j2ee.internal.plugin.IJ2EEModuleConstants;
import org.eclipse.jst.j2ee.internal.plugin.J2EEPlugin;
import org.eclipse.jst.j2ee.internal.project.J2EEProjectUtilities;
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.archive.IArchiveResource;
import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
import org.eclipse.wst.common.componentcore.resources.IVirtualContainer;

public class ConnectorComponentArchiveLoadAdapter extends ComponentArchiveLoadAdapter {

    private int dotJavaLength = JavaEEArchiveUtilities.DOT_JAVA.length();

    private List alreadyIndexed = new ArrayList();

    private Map classesMap;

    private IFile knownDD;

    public static String[] knownLibExtensions = { IJ2EEModuleConstants.JAR_EXT, ".zip", //$NON-NLS-1$
            ".so", //$NON-NLS-1$
            ".o", //$NON-NLS-1$
            ".sl", //$NON-NLS-1$
            ".dll", //$NON-NLS-1$
    };

    public ConnectorComponentArchiveLoadAdapter(IVirtualComponent vComponent) {
        this(vComponent, true);
    }

    public ConnectorComponentArchiveLoadAdapter(IVirtualComponent vComponent, boolean includeClasspathComponents) {
        super(vComponent, includeClasspathComponents);
        knownDD = vComponent.getRootFolder().getFile(J2EEConstants.RAR_DD_URI).getUnderlyingFile();
    }

    @Override
    public List<IArchiveResource> getArchiveResources() {
        if (shouldOptimize()) {
            attemptOptimization();
        }
        if (!membersOptimized) {
            addNestedJARsFromSourceRoots();
            aggregateSourceFiles();
        }
        return filesHolder.getFiles();
    }

    private void addNestedJARsFromSourceRoots() {
        IPackageFragmentRoot[] sourceRoots = J2EEProjectUtilities.getSourceContainers(vComponent.getProject());
        for (int i = 0; i < sourceRoots.length; i++) {
            IArchiveResource aFile;
            try {
                aFile = getNestedJar(sourceRoots[i]);
                if (null != aFile) {
                    filesHolder.addFile(aFile);
                }
            } catch (JavaModelException e) {
                J2EEPlugin.logError(e);
            } catch (ArchiveOpenFailureException e) {
                J2EEPlugin.logError(e);
            }
        }
    }

    private IArchiveResource getNestedJar(IPackageFragmentRoot sourceRoot)
            throws JavaModelException, ArchiveOpenFailureException {
        IPath outputPath = sourceRoot.getRawClasspathEntry().getOutputLocation();
        if (outputPath == null) {
            IProject project = vComponent.getProject();
            try {
                if (project.hasNature(JavaCore.NATURE_ID)) {
                    IJavaProject javaProject = JavaCore.create(project);
                    outputPath = javaProject.getOutputLocation();
                }
            } catch (CoreException e) {
                J2EEPlugin.logError(e);
            }
            if (outputPath == null) {
                return null;
            }
        }

        IFolder javaOutputFolder = ResourcesPlugin.getWorkspace().getRoot().getFolder(outputPath);
        indexClassesForOutputFolder(javaOutputFolder);
        IContainer sourceContainer = (IContainer) sourceRoot.getResource();

        int sourceContainerSegmentCount = sourceContainer.getProjectRelativePath().segmentCount();
        boolean isModuleRoot = knownDD.getProjectRelativePath().toString()
                .startsWith(sourceContainer.getProjectRelativePath().toString());
        Set iFilesSet = new HashSet();
        boolean foundJava = gatherFilesForJAR(iFilesSet, sourceContainer, isModuleRoot, false,
                sourceContainerSegmentCount);
        if (!isModuleRoot || foundJava) {
            List<IFile> iFilesList = Collections.list(Collections.enumeration(iFilesSet));
            for (int i = 0; i < iFilesList.size(); i++) {
                filesHolder.removeIFile(iFilesList.get(i));
            }
            IArchiveResource nestedArchive = createNestedArchive(iFilesList, sourceContainer, javaOutputFolder);
            return nestedArchive;
        }
        return null;
    }

    private boolean gatherFilesForJAR(Collection iFiles, IContainer current, boolean isModuleRoot,
            boolean foundJava, int sourceContainerSegmentCount) {
        IResource[] members = null;
        try {
            members = current.members();
        } catch (CoreException core) {
            // TODO
            // throw new ArchiveRuntimeException(core);
        }

        IContainer ddFolder = vComponent.getRootFolder().getFolder(J2EEConstants.META_INF).getUnderlyingFolder();

        boolean localFoundJava = foundJava;
        if (members != null) {
            for (int i = 0; i < members.length; i++) {
                IResource res = members[i];
                if (res.getType() == IResource.FOLDER) {
                    if (!ddFolder.equals(res)) {//if it's not the dd folder
                        localFoundJava = gatherFilesForJAR(iFiles, (IFolder) res, isModuleRoot, localFoundJava,
                                sourceContainerSegmentCount) || localFoundJava;
                    }
                } else {// it must be a file
                    IFile srcFile = (IFile) res;
                    if (belongsInNestedJAR(srcFile, isModuleRoot)) {
                        if (JavaEEArchiveUtilities.isJava(srcFile)) {
                            if (exportSource) {
                                iFiles.add(srcFile); // don't need to check
                                // duplicates here
                            }
                            String className = srcFile.getProjectRelativePath()
                                    .removeFirstSegments(sourceContainerSegmentCount).toString();
                            className = className.substring(0, className.length() - dotJavaLength);
                            List classes = retrieveClasses(className);
                            if (null != classes) {
                                Iterator iterator = classes.iterator();
                                while (iterator.hasNext()) {
                                    IFile clazz = (IFile) iterator.next();
                                    if (!iFiles.contains(clazz)) {
                                        // .class need to check for duplicates
                                        iFiles.add(clazz);
                                    }
                                }
                            }
                        } else {
                            if (!iFiles.contains(srcFile)) {
                                // if it's not src, then it could be .class and need
                                // to check for duplicates
                                iFiles.add(srcFile);
                            }
                        }
                        if (isModuleRoot)
                            localFoundJava = localFoundJava || JavaEEArchiveUtilities.isJava(srcFile)
                                    || JavaEEArchiveUtilities.isClass(srcFile);
                    }
                }
            }
        }
        return localFoundJava;
    }

    private IArchive createNestedArchive(List<IFile> files, IContainer sourceContainer, IFolder javaOutputFolder)
            throws ArchiveOpenFailureException {
        ConnectorComponentNestedJARArchiveLoadAdapter nestedLoader = new ConnectorComponentNestedJARArchiveLoadAdapter(
                files, sourceContainer, javaOutputFolder);
        ArchiveOptions nestedOptions = new ArchiveOptions();
        nestedOptions.setOption(ArchiveOptions.LOAD_ADAPTER, nestedLoader);
        IArchive nestedArchive = IArchiveFactory.INSTANCE.openArchive(nestedOptions);
        nestedArchive.setPath(new Path(computeUniqueArchiveURI(sourceContainer)));
        nestedArchive.setArchive(archive);
        return nestedArchive;
    }

    private String computeUniqueArchiveURI(IResource resource) {
        int increment = 0;
        String name = resource.getName();
        StringBuffer sb = null;
        do {
            sb = new StringBuffer(name.length() + 5);
            sb.append('_');
            sb.append(name);
            if (increment > 0)
                sb.append(increment);
            sb.append(IJ2EEModuleConstants.JAR_EXT);
            increment++;
        } while (filesHolder.contains(new Path(sb.toString())));
        return sb.toString();
    }

    private boolean belongsInNestedJAR(IFile iFile, boolean isModuleRoot) {
        if (isModuleRoot && isDeploymentDescriptor(iFile)) {
            return false;
        }
        for (int i = 0; i < knownLibExtensions.length; i++) {
            if (JavaEEArchiveUtilities.hasExtension(iFile, knownLibExtensions[i]))
                return false;
        }
        return true;
    }

    @Override
    protected boolean shouldInclude(IPath path) {
        String lastSegment = path.lastSegment();
        return null != lastSegment
                && !JavaEEArchiveUtilities.hasExtension(lastSegment, JavaEEArchiveUtilities.DOT_CLASS)
                && !JavaEEArchiveUtilities.hasExtension(lastSegment, JavaEEArchiveUtilities.DOT_JAVA);
    }

    /**
     * Find all the .class files and index them so inner classes can be located.
     */
    private void indexClassesForOutputFolder(IFolder javaOutputFolder) {
        if (null == javaOutputFolder || alreadyIndexed.contains(javaOutputFolder)) {
            return;
        }
        alreadyIndexed.add(javaOutputFolder);
        int segmentCount = javaOutputFolder.getProjectRelativePath().segmentCount();
        indexClasses(javaOutputFolder, segmentCount);
    }

    private void indexClasses(IResource resource, int javaOutputSegmentCount) {
        switch (resource.getType()) {
        case IResource.FILE:
            indexClass((IFile) resource, javaOutputSegmentCount);
            break;
        case IResource.FOLDER:
            try {
                IResource[] members = ((IFolder) resource).members();
                for (int i = 0; i < members.length; i++) {
                    indexClasses(members[i], javaOutputSegmentCount);
                }
            } catch (CoreException e) {
                J2EEPlugin.logError(e);
            }
            break;
        }
    }

    private void indexClass(IFile iFile, int javaOutputSegmentCount) {
        if (!JavaEEArchiveUtilities.isClass(iFile))
            return;
        if (classesMap == null)
            classesMap = new HashMap();
        String name = iFile.getName();
        IPath relPath = iFile.getProjectRelativePath().removeFirstSegments(javaOutputSegmentCount);
        String key = relPath.toString();
        if (name.indexOf('$') != -1) {
            key = key.substring(0, key.indexOf('$'));
        } else {
            key = key.substring(0, key.indexOf('.'));
        }
        List inners = (List) classesMap.get(key);
        if (inners == null) {
            inners = new ArrayList(1);
            classesMap.put(key, inners);
        }
        inners.add(iFile);
    }

    public List retrieveClasses(String key) {
        if (classesMap == null)
            return null;
        return (List) classesMap.get(key);
    }

    private boolean isDeploymentDescriptor(IFile iFile) {
        return knownDD.equals(iFile);
    }

    @Override
    protected IPath getDefaultModelObjectPath() {
        return new Path(J2EEConstants.RAR_DD_URI);
    }

    @Override
    protected boolean shouldInclude(IVirtualContainer vContainer) {
        boolean isDDFolder = vComponent.getRootFolder().getFolder(J2EEConstants.META_INF).equals(vContainer);
        return isDDFolder || !inJavaSrc(vContainer);
    }

}