/* * Copyright 2000-2012 JetBrains s.r.o. * * 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 * * 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 org.napile.idea.thermit.dom; import java.io.File; import java.io.IOException; import java.util.Collections; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.napile.idea.thermit.ReflectedProject; import org.napile.idea.thermit.config.ThermitConfigurationBase; import org.napile.idea.thermit.config.impl.AntBuildFileImpl; import org.napile.idea.thermit.config.impl.AntInstallation; import org.napile.idea.thermit.config.impl.GlobalThermitConfiguration; import org.napile.idea.thermit.config.impl.ThermitConfigurationImpl; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.projectRoots.ProjectJdkTable; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.pom.references.PomService; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFileSystemItem; import com.intellij.psi.xml.XmlElement; import com.intellij.psi.xml.XmlTag; import com.intellij.util.containers.HashMap; import com.intellij.util.xml.Attribute; import com.intellij.util.xml.Convert; import com.intellij.util.xml.DefinesXml; import com.intellij.util.xml.DomTarget; import com.intellij.util.xml.GenericAttributeValue; import com.intellij.util.xml.SubTagList; /** * @author Eugene Zhuravlev * Date: Apr 6, 2010 */ @SuppressWarnings({"AbstractClassNeverImplemented"}) @DefinesXml public abstract class AntDomProject extends AntDomNamedElement implements PropertiesProvider { private static final Logger LOG = Logger.getInstance(AntDomProject.class); @NonNls public static final String DEFAULT_ENVIRONMENT_PREFIX = "env."; private volatile ClassLoader myClassLoader; private volatile Map<String, String> myProperties; @Attribute("default") @Convert(value = AntDomDefaultTargetConverter.class) public abstract GenericAttributeValue<TargetResolver.Result> getDefaultTarget(); @Attribute("basedir") @Convert(value = AntPathConverter.class) public abstract GenericAttributeValue<PsiFileSystemItem> getBasedir(); @Nullable public final PsiFileSystemItem getProjectBasedir() { final PsiFileSystemItem basedir = getBasedir().getValue(); if(basedir != null) { return basedir; } final XmlTag tag = getXmlTag(); final VirtualFile containingFile = tag.getContainingFile().getOriginalFile().getVirtualFile(); if(containingFile == null) { return null; } final VirtualFile parent = containingFile.getParent(); if(parent == null) { return null; } return tag.getManager().findDirectory(parent); } @Nullable public final String getProjectBasedirPath() { final String basedir = getBasedir().getStringValue(); if(basedir != null) { final File file = new File(basedir); if(file.isAbsolute()) { try { return FileUtil.toSystemIndependentName(file.getCanonicalPath()); } catch(IOException e) { LOG.info(e); return null; } } } final String selfDir = getContainingFileDir(); if(basedir == null) { return selfDir; } // basedir is specified and is relative try { return FileUtil.toSystemIndependentName(new File(selfDir, basedir).getCanonicalPath()); } catch(IOException e) { LOG.info(e); return null; } } @Nullable public final String getContainingFileDir() { final VirtualFile containingFile = getXmlTag().getContainingFile().getOriginalFile().getVirtualFile(); if(containingFile == null) { return null; } final VirtualFile parent = containingFile.getParent(); return parent != null ? parent.getPath() : null; } @SubTagList("target") public abstract List<AntDomTarget> getDeclaredTargets(); @SubTagList("import") public abstract List<AntDomImport> getDeclaredImports(); @SubTagList("include") public abstract List<AntDomInclude> getDeclaredIncludes(); @Nullable public final AntDomTarget findDeclaredTarget(String declaredName) { for(AntDomTarget target : getDeclaredTargets()) { if(declaredName.equals(target.getName().getRawText())) { return target; } } return null; } @NotNull public final ClassLoader getClassLoader() { if(myClassLoader == null) { final XmlTag tag = getXmlTag(); final PsiFile containingFile = tag.getContainingFile(); final AntBuildFileImpl buildFile = (AntBuildFileImpl) ThermitConfigurationBase.getInstance(containingFile.getProject()).getAntBuildFile(containingFile); if(buildFile != null) { myClassLoader = buildFile.getClassLoader(); } else { AntInstallation antInstallation = getAntInstallation(); myClassLoader = antInstallation.getClassLoader(); } } return myClassLoader; } public AntInstallation getAntInstallation() { final ThermitConfigurationBase configuration = ThermitConfigurationBase.getInstance(getXmlTag().getProject()); AntInstallation antInstallation = null; if(configuration != null) { antInstallation = configuration.getProjectDefaultAnt(); } if(antInstallation == null) { antInstallation = GlobalThermitConfiguration.getInstance().getBundledAnt(); } assert antInstallation != null; return antInstallation; } @Nullable public final Sdk getTargetJdk() { final XmlTag tag = getXmlTag(); final PsiFile containingFile = tag.getContainingFile(); final AntBuildFileImpl buildFile = (AntBuildFileImpl) ThermitConfigurationBase.getInstance(containingFile.getProject()).getAntBuildFile(containingFile); if(buildFile != null) { String jdkName = AntBuildFileImpl.CUSTOM_JDK_NAME.get(buildFile.getAllOptions()); if(jdkName == null || jdkName.length() == 0) { jdkName = ThermitConfigurationImpl.DEFAULT_JDK_NAME.get(buildFile.getAllOptions()); } if(jdkName != null && jdkName.length() > 0) { return ProjectJdkTable.getInstance().findJdk(jdkName); } } return ProjectRootManager.getInstance(tag.getProject()).getProjectSdk(); } @NotNull public Iterator<String> getNamesIterator() { return getProperties().keySet().iterator(); } @Nullable public String getPropertyValue(String propertyName) { return getProperties().get(propertyName); } @Nullable public PsiElement getNavigationElement(String propertyName) { final DomTarget target = DomTarget.getTarget(this); final PsiElement nameElementPsi = target != null ? PomService.convertToPsi(target) : null; if(nameElementPsi != null) { return nameElementPsi; } final XmlElement xmlElement = getXmlElement(); return xmlElement != null ? xmlElement.getNavigationElement() : null; } private Map<String, String> getProperties() { Map<String, String> properties = myProperties; if(properties == null) { final ReflectedProject reflected = ReflectedProject.getProject(getClassLoader()); Map<String, String> externals = Collections.emptyMap(); final PsiFile containingFile = getXmlTag().getContainingFile(); if(containingFile != null) { final AntBuildFileImpl buildFile = (AntBuildFileImpl) ThermitConfigurationBase.getInstance(containingFile.getProject()).getAntBuildFile(containingFile); if(buildFile != null) { externals = buildFile.getExternalProperties(); } } myProperties = (properties = loadPredefinedProperties(reflected.getProperties(), externals)); } return properties; } @SuppressWarnings({"UseOfObsoleteCollectionType"}) private Map<String, String> loadPredefinedProperties(final Hashtable properties, final Map<String, String> externalProps) { final Map<String, String> destination = new HashMap<String, String>(); if(properties != null) { final Enumeration props = properties.keys(); while(props.hasMoreElements()) { final String name = (String) props.nextElement(); final String value = (String) properties.get(name); appendProperty(destination, name, value); } } //final Map<String, String> envMap = System.getenv(); //for (final String name : envMap.keySet()) { // if (name.length() > 0) { // final String value = envMap.get(name); // appendProperty(destination, DEFAULT_ENVIRONMENT_PREFIX + name, value); // } //} if(externalProps != null) { for(final String name : externalProps.keySet()) { final String value = externalProps.get(name); appendProperty(destination, name, value); } } String basedir = getProjectBasedirPath(); if(basedir == null) { basedir = "."; } if(!FileUtil.isAbsolute(basedir)) { final String containigFileDir = getContainingFileDir(); if(containigFileDir != null) { try { basedir = new File(containigFileDir, basedir).getCanonicalPath(); } catch(IOException e) { // ignore } } } if(basedir != null) { appendProperty(destination, "basedir", FileUtil.toSystemIndependentName(basedir)); } final AntInstallation installation = getAntInstallation(); final String homeDir = installation.getHomeDir(); if(homeDir != null) { appendProperty(destination, "thermit.home", FileUtil.toSystemIndependentName(homeDir)); } appendProperty(destination, "thermit.version", installation.getVersion()); final String projectName = getName().getRawText(); appendProperty(destination, "thermit.project.name", (projectName == null) ? "" : projectName); final Sdk jdkToRunWith = getTargetJdk(); final String version = jdkToRunWith != null ? jdkToRunWith.getVersionString() : null; appendProperty(destination, "thermit.java.version", version != null ? version : SystemInfo.JAVA_VERSION); final VirtualFile containingFile = getXmlTag().getContainingFile().getOriginalFile().getVirtualFile(); if(containingFile != null) { final String antFilePath = containingFile.getPath(); appendProperty(destination, "thermit.file", antFilePath); if(projectName != null) { appendProperty(destination, "thermit.file." + projectName, antFilePath); appendProperty(destination, "thermit.file.type." + projectName, "file"); } } return destination; } private static void appendProperty(final Map<String, String> map, String name, String value) { final String previous = map.put(name, value); if(previous != null) { map.put(name, previous); } } }