Java tutorial
/******************************************************************************* * 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><public></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><source></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; } }