com.google.gwt.eclipse.core.modules.ModuleFile.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gwt.eclipse.core.modules.ModuleFile.java

Source

/*******************************************************************************
 * Copyright 2011 Google Inc. All Rights Reserved.
 *
 * 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
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *******************************************************************************/
package com.google.gwt.eclipse.core.modules;

import com.google.gdt.eclipse.core.properties.WebAppProjectProperties;
import com.google.gwt.eclipse.core.GWTPluginLog;
import com.google.gwt.eclipse.core.util.Util;

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.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.eclipse.wst.xml.core.internal.provisional.format.FormatProcessorXML;
import org.w3c.dom.Element;

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

/**
 * Represents a GWT module file (.gwt.xml) on disk.
 */
@SuppressWarnings("restriction")
public class ModuleFile extends AbstractModule {

    // TODO: use XmlUtilities.EditOperation instead
    private abstract class EditModelOperation {

        public void run() {
            IDOMModel model = null;
            try {
                model = getModelForEdit();
                model.aboutToChangeModel();

                // Now do something to the model
                editModel(model);

                // Notify listeners that we've changed the model
                model.changedModel();

                // Save the model if necessary
                if (!model.isSharedForEdit() && model.isSaveNeeded()) {
                    model.save();
                }
            } catch (IOException e) {
                GWTPluginLog.logError(e);
            } catch (CoreException e) {
                GWTPluginLog.logError(e);
            } finally {
                if (model != null) {
                    model.releaseFromEdit();
                }
            }
        }

        protected abstract void editModel(IDOMModel model);

        private IDOMModel getModelForEdit() throws IOException, CoreException {
            IModelManager modelManager = StructuredModelManager.getModelManager();
            return (IDOMModel) modelManager.getModelForEdit(getFile());
        }
    }

    protected ModuleFile(IFile file) {
        super(file);
    }

    /**
     * Adds a new entry point to a module.
     *
     * @param qualifiedTypeName name of the entry point class, which should
     *        com.google.gwt.core.client.EntryPoint
     * @throws Exception if there was a problem modifying or saving the module XML
     */
    public void addEntryPoint(final String qualifiedTypeName) throws Exception {
        new EditModelOperation() {
            @Override
            public void editModel(IDOMModel model) {
                IDOMDocument editDoc = model.getDocument();

                // TODO: create an empty element (no closing </entry-point>)

                Element entryPointElement = editDoc.createElement(ENTRY_POINT_TAG_NAME);
                entryPointElement.setAttribute(CLASS_ATTRIBUTE_NAME, qualifiedTypeName);
                editDoc.getDocumentElement().appendChild(entryPointElement);

                // Reformat the XML source to keep it nice and neat
                new FormatProcessorXML().formatModel(model);
            }
        }.run();
    }

    /**
     * Returns the backing IFile for the module XML file.
     *
     * @return IFile referencing the module XML
     */
    public IFile getFile() {
        // We received storage as an IFile in our ctor, so we know this cast works
        return (IFile) storage;
    }

    /**
     * Returns the IFolder corresponding to a path relative to this module. The IFolder is just a
     * resource handle; call its exists() method before using.
     *
     * TODO: wrap public, source, and super-src paths in a class and add this as an instance method?
     *
     * @param moduleRelativePath module-relative path
     * @return IFolder corresponding to the path
     */
    public IFolder getFolder(IPath moduleRelativePath) {
        IPath moduleFolderPath = storage.getFullPath().removeLastSegments(1);
        IPath folderPath = moduleFolderPath.append(moduleRelativePath);
        IResource folder = Util.getWorkspaceRoot().findMember(folderPath);
        return (IFolder) folder;
    }

    // TODO: move this to class that wraps higher-level DOM elements (entry
    // points, source paths, inherited modules, etc.) and links them to source
    // positions
    public int getLineOfOffset(final int offset) {
        final int[] line = new int[1];

        new ReadModelOperation() {
            @Override
            protected void readModel(IDOMModel model) {
                line[0] = model.getStructuredDocument().getLineOfOffset(offset);
            }
        }.run();

        return line[0];
    }

    @Override
    public boolean isBinary() {
        return false;
    }

    /**
     * Returns whether a folder is on the public path of this module. The public paths include the
     * paths explicitly declared with <code>&lt;public&gt;</code> tags and all of their descendant
     * sub-folders.
     *
     * @param folder the folder to check
     * @return <code>true</code> if this folder is on a public path, and <code>false</code> otherwise
     */
    public boolean isPublicPath(IFolder folder) {
        IFolder[] publicFolders = getFolders(getPublicPaths());

        IContainer moduleContainer = getFile().getParent();
        IContainer container = folder;

        // Walk up the ancestor chain looking for a public path matching this folder
        while (container.getType() == IResource.FOLDER) {
            // If we reach the module's container, we're done searching
            if (container.equals(moduleContainer)) {
                return false;
            }

            for (IFolder publicFolder : publicFolders) {
                if (container.equals(publicFolder)) {
                    return true;
                }
            }

            container = container.getParent();
        }

        return false;
    }

    /**
     * <p>
     * Returns whether a package is on the client source path of this module. The source paths include
     * the paths explicitly declared with <code>&lt;source&gt;</code> tags and all of their descendant
     * packages.
     * </p>
     * <p>
     * For example, if a module is located in <code>com.hello</code> and has the default client source
     * path "client", then <code>com.hello.client</code> and <code>com.hello.client.utils</code> would
     * both return true.
     * </p>
     *
     * @param pckg package to check
     * @return <code>true</code> if this package is on a client source path, and <code>false</code>
     *         otherwise
     */
    public boolean isSourcePackage(IPackageFragment pckg) {
        IResource resource = pckg.getResource();
        if (resource.getType() == IResource.FOLDER) {
            IPath pckgFolderPath = resource.getFullPath();

            // Check each source path to see if it's an ancestor of this package
            for (IFolder clientFolder : getFolders(getSourcePaths())) {
                IPath clientFolderPath = clientFolder.getFullPath();
                if (clientFolderPath.isPrefixOf(pckgFolderPath)) {
                    return true;
                }
            }
        }

        return false;
    }

    @Override
    protected IDOMModel doGetModelForRead() throws IOException, CoreException {
        IModelManager modelManager = StructuredModelManager.getModelManager();
        return (IDOMModel) modelManager.getModelForRead(getFile());
    }

    @Override
    protected String doGetPackageName() {
        IFolder moduleFolder = (IFolder) getFile().getParent();
        IJavaElement javaElement = JavaCore.create(moduleFolder);

        // Maven module name - maven 1 or maven 2 plugins
        String mavenModuleName = WebAppProjectProperties.getGwtMavenModuleName(moduleFolder.getProject());

        // not null, then it must be a gwt maven project 2
        String shortName = WebAppProjectProperties.getGwtMavenModuleShortName(moduleFolder.getProject());
        if (mavenModuleName != null && !mavenModuleName.isEmpty() && shortName != null && !shortName.isEmpty()
                && mavenModuleName.contains(".")) {
            String gwtMavenPackage2 = mavenModuleName.replaceAll("(.*)\\..*", "$1");
            return gwtMavenPackage2;
        }

        if (javaElement != null) {
            if (javaElement.getElementType() == IJavaElement.PACKAGE_FRAGMENT) {
                return javaElement.getElementName();
            }
        } else {
            // TODO: handle super-source case here
        }

        return "";
    }

    /**
     * Get the GWT Maven Module package from GWT plugin 2 module.gwt.xml.
     *
     * @param project
     * @return the module path
     */
    private IJavaElement getGwtMavenModuleNameForGwtMavenPlugin2(IProject project) {
        if (project == null) {
            return null;
        }

        IFolder moduleFolder = (IFolder) getFile().getParent();

        // For GWT maven plugin 2, its module is in src/main
        if (!moduleFolder.toString().contains("src/main")) {
            return null;
        }

        IJavaProject javaProject = JavaCore.create(project);
        if (javaProject == null) {
            return null;
        }

        String moduleName = WebAppProjectProperties.getGwtMavenModuleName(project);
        if (moduleName == null || !moduleName.contains(".")) {
            return null;
        }

        String[] moduleNameParts = moduleName.split("\\.");

        IPath path = moduleFolder.getFullPath().append("java");
        for (int i = 0; i < moduleNameParts.length - 1; i++) {
            path = path.append(moduleNameParts[i]);
        }

        try {
            return javaProject.findPackageFragment(path);
        } catch (JavaModelException e) {
            return null;
        }
    }

    /**
     * Find the Source folder for the src/main/.../client
     *
     * TODO won't work b/c super source could have a client, or some other path before it.
     *
     * @param moduleFolder
     * @return The source package java for client
     */
    private IJavaElement findSourceFolderElement(IFolder moduleFolder) {
        // TODO red the source attrbute in the module and find it?
        IFolder folderSourcePackage = findSourcePackage(moduleFolder, "client");
        if (folderSourcePackage == null) {
            return null;
        }

        IJavaProject javaProject = JavaCore.create(folderSourcePackage.getProject());
        if (javaProject == null) {
            return null;
        }

        try {
            IPackageFragment clientPackage = javaProject.findPackageFragment(folderSourcePackage.getFullPath());
            return clientPackage;
        } catch (JavaModelException e) {
            e.printStackTrace();
        }

        return null;
    }

    private IFolder[] getFolders(List<IPath> paths) {
        List<IFolder> folders = new ArrayList<IFolder>();
        for (IPath path : paths) {
            IFolder folder = getFolder(path);
            if (folder != null) {
                folders.add(folder);
            }
        }
        return folders.toArray(new IFolder[0]);
    }

    /**
     * Find the folder with name.
     *
     * @param folder
     * @param name
     * @return the folder found
     */
    private IFolder findSourcePackage(IFolder folder, String name) {
        IResource[] members = null;
        try {
            members = folder.members();
        } catch (CoreException e) {
            return null;
        }
        if (members == null) {
            return null;
        }
        for (IResource member : members) {
            if (member.getType() == IResource.FOLDER) {
                if (member.getName().equals(name)) {
                    return folder;
                }
                return findSourcePackage((IFolder) member, name);
            }
        }
        return null;
    }

}