org.ebayopensource.turmeric.eclipse.buildsystem.utils.BuilderUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.ebayopensource.turmeric.eclipse.buildsystem.utils.BuilderUtil.java

Source

/*******************************************************************************
 * Copyright (c) 2006-2010 eBay Inc. All Rights Reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *******************************************************************************/
package org.ebayopensource.turmeric.eclipse.buildsystem.utils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.wsdl.Definition;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.ebayopensource.turmeric.eclipse.buildsystem.resources.SOAMessages;
import org.ebayopensource.turmeric.eclipse.core.logging.SOALogger;
import org.ebayopensource.turmeric.eclipse.core.resources.constants.SOAProjectConstants;
import org.ebayopensource.turmeric.eclipse.exception.core.SOANullParameterException;
import org.ebayopensource.turmeric.eclipse.exception.resources.SOAResourceNotAccessibleException;
import org.ebayopensource.turmeric.eclipse.repositorysystem.model.BaseCodeGenModel;
import org.ebayopensource.turmeric.eclipse.repositorysystem.utils.TurmericServiceUtils;
import org.ebayopensource.turmeric.eclipse.resources.model.ISOAConsumerProject.SOAClientConfig;
import org.ebayopensource.turmeric.eclipse.resources.model.SOAImplMetadata;
import org.ebayopensource.turmeric.eclipse.resources.util.SOAConsumerUtil;
import org.ebayopensource.turmeric.eclipse.resources.util.SOAImplUtil;
import org.ebayopensource.turmeric.eclipse.resources.util.SOAServiceUtil;
import org.ebayopensource.turmeric.eclipse.utils.lang.StringUtil;
import org.ebayopensource.turmeric.eclipse.utils.plugin.JDTUtil;
import org.ebayopensource.turmeric.eclipse.utils.plugin.ProgressUtil;
import org.ebayopensource.turmeric.eclipse.utils.plugin.WorkspaceUtil;
import org.ebayopensource.turmeric.eclipse.utils.wsdl.WSDLUtil;
import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;

/**
 * The standard Utility class for the builder. Most builders will need the code
 * generation models and engine in their functions. This utility mainly caters
 * these two objects so that the builder has a commonality in the way in which
 * they invoke the code generation engine.
 * 
 * @author smathew
 * 
 */
public class BuilderUtil {

    /**
     * Foundation Code generation Model for builders. This is the base code
     * generation model which will be specialized before used in most cases.
     * Fills the metadata file(properties file) information into this model. All
     * the common data that any model required will be filled in at this phase.
     * But The gen type that is the most crucial factor is not decided here. It
     * is decided in the specialization phase. Its also called heavily from
     * context menu actions which includes codegen.
     *
     * @param project the project
     * @param monitor the monitor
     * @return the base code gen model
     * @throws Exception the exception
     */
    public static BaseCodeGenModel buildBaseCodeGenModel(final IProject project, final IProgressMonitor monitor)
            throws Exception {
        return ModelTransformer.generateCodeGenModel(project, monitor);
    }

    /**
     * Returns trues if the WSDL file is changed. This is not a straight forward
     * API. It does not care about the changes in the WSDL file if it is not an
     * interface projects. So please don't use it as a generic API.
     *
     * @param delta the delta
     * @param project the project
     * @return true, if is wSDL file changed
     * @throws CoreException the core exception
     */
    public static boolean isWSDLFileChanged(IResourceDelta delta, IProject project) throws CoreException {
        if (TurmericServiceUtils.isSOAInterfaceProject(project) == false)
            return false;
        final IFile wsdlFile = SOAServiceUtil.getWsdlFile(project, project.getName());
        return isWSDLFileChanged(delta, wsdlFile.getFullPath());
    }

    /**
     * Parses the delta and returns true if the WSDL file is changed. Recursive
     * function but does not use the visitor pattern.
     * 
     * @param delta
     * @param wsdlPath
     * @return
     */
    private static boolean isWSDLFileChanged(IResourceDelta delta, IPath wsdlPath) {
        if (delta == null)
            return false;
        for (IResourceDelta childDelta : delta.getAffectedChildren(IResourceDelta.CHANGED)) {
            if (childDelta.getFullPath().equals(wsdlPath))
                return true;
            else if (isWSDLFileChanged(childDelta, wsdlPath)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Returns true if the WSDL target name space has been changed in an
     * interface project. To be precise, it does NOT compare the WSDl's old name
     * space and the new name space, but compares the WSDL's current namespace
     * to the namespace in the implementation projects metadata file.
     *
     * @param delta the delta
     * @param serviceName the service name
     * @param intfProject the intf project
     * @param implProject the impl project
     * @return null means no change or the new targetNamespace otherwise.
     * @throws Exception the exception
     */
    public static String isWSDLTargetNamespaceChanged(IResourceDelta delta, String serviceName,
            IProject intfProject, IProject implProject) throws Exception {
        final IFile wsdlFile = SOAServiceUtil.getWsdlFile(intfProject, serviceName);
        if (isWSDLFileChanged(delta, wsdlFile.getFullPath()) == false)
            return null;
        final Definition wsdl = WSDLUtil.readWSDL(wsdlFile.getLocation().toString());
        final SOAImplMetadata metadata = SOAImplUtil.loadServiceConfig(implProject, serviceName);
        if (!StringUtils.equals(wsdl.getTargetNamespace(), metadata.getTargetNamespace())) {
            return wsdl.getTargetNamespace();
        }
        return null;
    }

    /**
     * Returns true if the WSDL target name space has been changed in an
     * interface project. To be precise, it does NOT compare the WSDl's old name
     * space and the new name space, but compares the WSDL's current namespace
     * to the namespace in the client config file of the consumer.
     *
     * @param serviceName the service name
     * @param intfProject the intf project
     * @param consumerProject the consumer project
     * @return null means no change or the new targetNamespace otherwise.
     * @throws Exception the exception
     */
    public static String isWSDLTargetNamespaceChangedInConsumerProject(String serviceName, IProject intfProject,
            IProject consumerProject) throws Exception {
        final IFile wsdlFile = SOAServiceUtil.getWsdlFile(intfProject, serviceName);
        if (wsdlFile.isAccessible() == false)
            return null;
        final Definition wsdl = WSDLUtil.readWSDL(wsdlFile.getLocation().toString());
        String envName = null;
        if (SOAConsumerUtil.isOldClientConfigDirStructure(consumerProject) == false) {
            List<String> envs = SOAConsumerUtil.getClientEnvironmentList(consumerProject, null);
            if (envs.isEmpty() == false)
                envName = envs.get(0);
        }

        final SOAClientConfig clientConfig = SOAConsumerUtil.loadClientConfig(consumerProject, envName,
                serviceName);
        if (clientConfig == null)
            return null;
        if (!StringUtils.equals(wsdl.getTargetNamespace(), clientConfig.getTargetNamespace())) {
            return wsdl.getTargetNamespace();
        }
        return null;
    }

    /**
     * This algorithm is the decision maker for all SOA builders. If this is
     * true builder gets kicked off and return silently otherwise. Remember
     * there are two builders most of the time and its very imp to silently
     * return at some point of time to avoid cyclic builds.
     *
     * @param delta the delta
     * @param project the project
     * @param criteriaString -
     * this is mostly the extensions that we are interested in
     * rebuilding. something like WSDT EXT, XSD EXT etc
     * @return true, if successful
     * @throws Exception the exception
     */
    public static boolean shouldBuild(IResourceDelta delta, IProject project, String... criteriaString)
            throws Exception {
        // first time the delta is null
        if (delta == null)
            return true;
        BuildResourceDeltaVisitor buildDeltaVisitor = new BuildResourceDeltaVisitor(project, criteriaString);
        delta.accept(buildDeltaVisitor);
        return buildDeltaVisitor.isBuildRequired();
    }

    /**
     * This is required because V3 appears to mess with the build order. This
     * will stay here until V3 comes up with a bug fix.
     *
     * @param project the project
     * @throws CoreException the core exception
     */
    public static void reOrderBuildersIfRequired(IProject project) throws CoreException {
        ICommand commands[] = project.getDescription().getBuildSpec();
        List<ICommand> oldList = Arrays.asList(commands);
        List<ICommand> newList = new ArrayList<ICommand>();
        for (ICommand command : commands) {
            newList.add(command);
        }

        // Scanning if the order has changed
        for (int i = 0; i < newList.size(); i++) {
            // true means order changed
            if (!StringUtils.equals(oldList.get(i).getBuilderName(), newList.get(i).getBuilderName())) {
                IProjectDescription description = project.getDescription();
                description.setBuildSpec(newList.toArray(new ICommand[0]));
                project.setDescription(description, IResource.FORCE, ProgressUtil.getDefaultMonitor(null));
            }
        }
    }

    /**
     * Cleans the bin/META-INF folder and do a refresh.
     *
     * @param project the project
     * @param monitor the monitor
     * @throws IOException Signals that an I/O exception has occurred.
     * @throws CoreException the core exception
     */
    public static void cleanBinMetaInfDir(final IProject project, IProgressMonitor monitor)
            throws IOException, CoreException {
        final IFolder metaFolder = project.getFolder(SOAProjectConstants.FOLDER_OUTPUT_DIR
                + WorkspaceUtil.PATH_SEPERATOR + SOAProjectConstants.FOLDER_META_INF);
        metaFolder.getParent().refreshLocal(IResource.DEPTH_ONE, monitor);
        if (metaFolder.isAccessible()) {
            SOALogger.getLogger()
                    .warning(StringUtil.formatString(SOAMessages.CLEAN_FOLDER, metaFolder.getLocation()));
            FileUtils.cleanDirectory(metaFolder.getLocation().toFile());
        }
    }

    /**
     * Returns the required project for any given project. Scans the build bath
     * and finds all the project references and returns it back.
     *
     * @param project the project
     * @param natureIds the nature ids
     * @return the required projects
     */
    public static IProject[] getRequiredProjects(IProject project, String... natureIds) {
        IJavaProject javaProject = JavaCore.create(project);
        if (javaProject == null)
            return new IProject[0];
        ArrayList<IProject> projects = new ArrayList<IProject>();
        try {
            for (final IClasspathEntry entry : javaProject.getResolvedClasspath(true)) {
                if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
                    IProject reqProject = WorkspaceUtil.getProject(entry.getPath());
                    if (reqProject != null && !projects.contains(reqProject)) {
                        if (natureIds != null) {
                            for (String natureId : natureIds) {
                                if (reqProject.hasNature(natureId)) {
                                    projects.add(reqProject);
                                    break;
                                }
                            }
                        } else {
                            projects.add(reqProject);
                        }
                    }
                }
            }
        } catch (Exception e) {
            return new IProject[0];
        }
        IProject[] result = new IProject[projects.size()];
        projects.toArray(result);
        return result;
    }

    /**
     * Creates missing source folders as per the projects java model. If it
     * exists, it is a no operation.
     *
     * @param project the project
     * @param monitor the monitor
     * @throws CoreException the core exception
     */
    public static void generateSourceDirectories(final IProject project, final IProgressMonitor monitor)
            throws CoreException {
        if (project == null || project.isAccessible() == false)
            return;
        final IPath projectPath = project.getFullPath();
        final List<String> missingFolders = new ArrayList<String>();
        for (IPath srcPath : JDTUtil.getSourceDirectories(project)) {
            if (projectPath.isPrefixOf(srcPath)) {
                srcPath = srcPath.removeFirstSegments(1);
            }
            final IFolder srcFolder = project.getFolder(srcPath);
            if (!srcFolder.exists()) {
                srcFolder.refreshLocal(IResource.DEPTH_ZERO, monitor);
                if (srcFolder.exists() == false) {
                    missingFolders.add(srcPath.toString());
                }
            }
        }
        if (missingFolders.isEmpty() == false) {
            WorkspaceUtil.createFolders(project, missingFolders, monitor);
        }
    }

    /**
     * Deletes the gen folder content of interface projects(for now). The types
     * are generated in the folder and we don't want stale java types to live
     * there. Washing it out in this call.
     *
     * @param project the project
     * @throws CoreException the core exception
     * @throws SOANullParameterException the sOA null parameter exception
     * @throws SOAResourceNotAccessibleException the sOA resource not accessible exception
     */
    public static void cleanGenFolders(IProject project)
            throws CoreException, SOANullParameterException, SOAResourceNotAccessibleException {
        // Intf Project
        if (TurmericServiceUtils.isSOAInterfaceProject(project)) {
            IFolder clientFolder = project.getFolder(SOAProjectConstants.FOLDER_GEN_SRC_CLIENT);
            WorkspaceUtil.deleteContents(clientFolder, true);

        }
    }
}