/********************************************************************** * Copyright (c) 2005-2009 ant4eclipse project team. * * 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: * Nils Hartmann, Daniel Kasmeroglu, Gerd Wuetherich **********************************************************************/ package org.ant4eclipse.lib.platform.internal.model.resource.workspaceregistry; import org.ant4eclipse.lib.core.Assure; import org.ant4eclipse.lib.core.exception.Ant4EclipseException; import org.ant4eclipse.lib.core.service.ServiceRegistryAccess; import org.ant4eclipse.lib.core.util.Utilities; import org.ant4eclipse.lib.core.xquery.XQuery; import org.ant4eclipse.lib.core.xquery.XQueryHandler; import org.ant4eclipse.lib.platform.PlatformExceptionCode; import org.ant4eclipse.lib.platform.internal.model.resource.BuildCommandImpl; import org.ant4eclipse.lib.platform.internal.model.resource.EclipseProjectImpl; import org.ant4eclipse.lib.platform.internal.model.resource.LinkedResourceImpl; import org.ant4eclipse.lib.platform.internal.model.resource.ProjectNatureImpl; import org.ant4eclipse.lib.platform.model.resource.EclipseProject; import org.ant4eclipse.lib.platform.model.resource.LinkedResourcePathVariableService; import org.ant4eclipse.lib.platform.model.resource.variable.EclipseStringSubstitutionService; import java.io.File; import java.util.StringTokenizer; /** * <p> * Parser that reads an eclipse <code>.project</code> file and creates an * {@link org.ant4eclipse.lib.platform.model.resource.EclipseProject EclipseProject}. * </p> * * @author Gerd Wütherich (gerd@gerd-wuetherich.de) */ public class ProjectFileParser { /** * <p> * Parses the '<code>.project</code>' file of the given eclipse project. * </p> * * @param eclipseProject * * @return the supplied {@link EclipseProject} instance. */ public static EclipseProjectImpl parseProject(EclipseProjectImpl eclipseProject) { Assure.notNull("eclipseProject", eclipseProject); // retrieve the '.project' file File projectFile = eclipseProject.getChild(".project"); XQueryHandler queryhandler2 = new XQueryHandler(projectFile.getAbsolutePath()); // create Queries XQuery projectNameQuery = queryhandler2.createQuery("/projectDescription/name"); XQuery commentQuery = queryhandler2.createQuery("/projectDescription/comment"); XQuery referencedProjectQuery = queryhandler2.createQuery("/projectDescription/projects/project"); XQuery natureQuery = queryhandler2.createQuery("/projectDescription/natures/nature"); XQuery buildCommandNameQuery = queryhandler2.createQuery("/projectDescription/buildSpec/{buildCommand}/name"); XQuery linkedResourceNameQuery = queryhandler2.createQuery("/projectDescription/linkedResources/{link}/name"); XQuery linkedResourceTypeQuery = queryhandler2.createQuery("/projectDescription/linkedResources/{link}/type"); XQuery linkedResourceLocationQuery = queryhandler2 .createQuery("/projectDescription/linkedResources/{link}/location"); XQuery linkedResourceLocationURIQuery = queryhandler2 .createQuery("/projectDescription/linkedResources/{link}/locationURI"); XQueryHandler.queryFile(projectFile, queryhandler2); String projectName = projectNameQuery.getSingleResult(); String comment = commentQuery.getSingleResult(); String[] referencedProjects = referencedProjectQuery.getResult(); String[] natures = natureQuery.getResult(); String[] buildCommandNames = buildCommandNameQuery.getResult(); String[] linkedResourceNames = linkedResourceNameQuery.getResult(); String[] linkedResourceTypes = linkedResourceTypeQuery.getResult(); String[] linkedResourceLocations = linkedResourceLocationQuery.getResult(); String[] linkedResourceLocationURIs = linkedResourceLocationURIQuery.getResult(); // set specified name eclipseProject.setSpecifiedName(projectName); // set comment eclipseProject.setComment(comment); // set referenced projects for (String referencedProject : referencedProjects) { eclipseProject.addReferencedProject(referencedProject); } // set project natures for (String nature : natures) { eclipseProject.addNature(new ProjectNatureImpl(nature)); } // set build commands for (String buildCommandName : buildCommandNames) { eclipseProject.addBuildCommand(new BuildCommandImpl(buildCommandName)); } // set linked resources for (int i = 0; i < linkedResourceNames.length; i++) { // retrieve location and locationURI String locationuri = linkedResourceLocationURIs[i]; String location = linkedResourceLocations[i]; // if (locationuri != null) { location = resolveLocation(eclipseProject, locationuri); if (location == null) { // resolving the variable failed for some reason // TODO!! throw (new RuntimeException("couldn't resolve variable '" + locationuri + "'")); } } else { // this is needed since variable names are stored under the <location> element // in eclipse versions before 3.2. this is some sort of guessing since String newlocation = location; int first = newlocation.indexOf('/'); if (first != -1) { // only the part until the first slash can refer to a variable name newlocation = newlocation.substring(0, first); } newlocation = resolveLocation(eclipseProject, newlocation); if (newlocation != null) { File test = new File(newlocation); if (test.exists()) { if (first != -1) { // the content has been cut down, so we need to add the relative path here location = newlocation + location.substring(first); } else { location = newlocation; } } } } // File locationAsFile = new File(location); if (!locationAsFile.exists() && location.contains("/")) { String variableName = location.substring(0, location.indexOf("/")); LinkedResourcePathVariableService variableService = ServiceRegistryAccess.instance().getService( LinkedResourcePathVariableService.class); String variable = variableService.getLinkedResourcePath(variableName); if (variable != null) { location = variable + location.substring(location.indexOf("/")); locationAsFile = new File(location); } } // throw exception if file does not exist if (!locationAsFile.exists()) { throw new Ant4EclipseException(PlatformExceptionCode.LINKED_RESOURCE_DOES_NOT_EXIST, locationAsFile .getAbsolutePath(), projectName); } String relative = Utilities.calcRelative(eclipseProject.getFolder(), locationAsFile); int typeAsInt = Integer.parseInt(linkedResourceTypes[i]); LinkedResourceImpl linkedResource = new LinkedResourceImpl(linkedResourceNames[i], location, relative, typeAsInt); eclipseProject.addLinkedResource(linkedResource); } return eclipseProject; } /** * Determines whether a given directory is an eclipse project directory * * @param directory * the directory to test * @return true, if the directory is an eclipse project directory */ public static boolean isProjectDirectory(File directory) { return directory != null && directory.exists() && directory.isDirectory() && new File(directory, ".project").exists(); } /* * TODO: * * Mostly unlikely, some weird path may be presented, so checking for extraneous separators may be worthwhile in the * long run. */ private static final String resolveLocation(EclipseProjectImpl p, String path) { if (path == null) { return null; } String S = "/"; StringTokenizer t = new StringTokenizer(path, S); StringBuffer b = new StringBuffer(path.length() * 3); while (t.hasMoreElements()) { String segment = (String) t.nextElement(); if (segment == null) { return null; } String resolved = getLocation(p, segment); if (resolved != null) { b.append(resolved); } else { b.append(segment); } if (t.hasMoreElements()) { b.append(S); } } return b.toString(); } /** * Returns the location while expanding the supplied variable. * * @param eclipseProject * The project that will be used for the variable expansion. * @param variable * The name of the variable. * * @return The expanded variable or null in case no expansion happened. */ private static final String getLocation(EclipseProjectImpl eclipseProject, String variable) { String key = "${" + variable + "}"; String location = getEclipseVariableResolver().substituteEclipseVariables(key, eclipseProject, null); if (key.equals(location)) { // fallback for the internal prefs of an eclipse .metadata dir key = "${pathvariable." + variable + "}"; location = getEclipseVariableResolver().substituteEclipseVariables(key, eclipseProject, null); if (key.equals(location)) { // the result is the key itself, so resolving failed location = null; } } return location; } private static EclipseStringSubstitutionService getEclipseVariableResolver() { EclipseStringSubstitutionService resolver = ServiceRegistryAccess.instance().getService( EclipseStringSubstitutionService.class); return resolver; } } /* ENDCLASS */