blob: 0422898a2bbb8e620f4cba62863a5196a2ad0b64 [file] [log] [blame]
/*
* Copyright 2000-2009 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.jetbrains.idea.maven.dom;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.xml.XmlElement;
import com.intellij.psi.xml.XmlTag;
import org.jdom.Element;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.dom.model.MavenDomProfile;
import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel;
import org.jetbrains.idea.maven.dom.model.MavenDomProperties;
import org.jetbrains.idea.maven.dom.references.MavenFilteredPropertyPsiReferenceProvider;
import org.jetbrains.idea.maven.model.MavenId;
import org.jetbrains.idea.maven.project.MavenProject;
import org.jetbrains.idea.maven.project.MavenProjectsManager;
import org.jetbrains.idea.maven.server.MavenServerUtil;
import org.jetbrains.idea.maven.utils.MavenJDOMUtil;
import org.jetbrains.idea.maven.utils.MavenUtil;
import org.jetbrains.jps.maven.compiler.MavenEscapeWindowsCharacterUtils;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MavenPropertyResolver {
public static final Pattern PATTERN = Pattern.compile("\\$\\{(.+?)\\}|@(.+?)@");
public static void doFilterText(Module module,
String text,
Properties additionalProperties,
@Nullable String propertyEscapeString,
Appendable out) throws IOException {
MavenProjectsManager manager = MavenProjectsManager.getInstance(module.getProject());
MavenProject mavenProject = manager.findProject(module);
if (mavenProject == null) {
out.append(text);
return;
}
Element pluginConfiguration = mavenProject.getPluginConfiguration("org.apache.maven.plugins", "maven-resources-plugin");
String escapeWindowsPathsStr = MavenJDOMUtil.findChildValueByPath(pluginConfiguration, "escapeWindowsPaths");
boolean escapeWindowsPath = escapeWindowsPathsStr == null || Boolean.parseBoolean(escapeWindowsPathsStr);
doFilterText(MavenFilteredPropertyPsiReferenceProvider.getDelimitersPattern(mavenProject),
manager,
mavenProject,
text,
additionalProperties,
propertyEscapeString,
escapeWindowsPath,
null,
out);
}
private static void doFilterText(Pattern pattern,
MavenProjectsManager mavenProjectsManager,
MavenProject mavenProject,
String text,
Properties additionalProperties,
@Nullable String escapeString,
boolean escapeWindowsPath,
@Nullable Map<String, String> resolvedPropertiesParam,
Appendable out) throws IOException {
Map<String, String> resolvedProperties = resolvedPropertiesParam;
Matcher matcher = pattern.matcher(text);
int groupCount = matcher.groupCount();
int last = 0;
while (matcher.find()) {
if (escapeString != null) {
int escapeStringStartIndex = matcher.start() - escapeString.length();
if (escapeStringStartIndex >= last) {
if (text.startsWith(escapeString, escapeStringStartIndex)) {
out.append(text, last, escapeStringStartIndex);
out.append(matcher.group());
last = matcher.end();
continue;
}
}
}
out.append(text, last, matcher.start());
last = matcher.end();
String propertyName = null;
for (int i = 0; i < groupCount; i++) {
propertyName = matcher.group(i + 1);
if (propertyName != null) {
break;
}
}
assert propertyName != null;
if (resolvedProperties == null) {
resolvedProperties = new HashMap<String, String>();
}
String propertyValue = resolvedProperties.get(propertyName);
if (propertyValue == null) {
if (resolvedProperties.containsKey(propertyName)) { // if cyclic property dependencies
out.append(matcher.group());
continue;
}
String resolved = doResolveProperty(propertyName, mavenProjectsManager, mavenProject, additionalProperties);
if (resolved == null) {
out.append(matcher.group());
continue;
}
resolvedProperties.put(propertyName, null);
StringBuilder sb = new StringBuilder();
doFilterText(pattern, mavenProjectsManager, mavenProject, resolved, additionalProperties, null, escapeWindowsPath, resolvedProperties, sb);
propertyValue = sb.toString();
resolvedProperties.put(propertyName, propertyValue);
}
if (escapeWindowsPath) {
MavenEscapeWindowsCharacterUtils.escapeWindowsPath(out, propertyValue);
}
else {
out.append(propertyValue);
}
}
out.append(text, last, text.length());
}
public static String resolve(String text, MavenDomProjectModel projectDom) {
XmlElement element = projectDom.getXmlElement();
if (element == null) return text;
VirtualFile file = MavenDomUtil.getVirtualFile(element);
if (file == null) return text;
MavenProjectsManager manager = MavenProjectsManager.getInstance(projectDom.getManager().getProject());
MavenProject mavenProject = manager.findProject(file);
if (mavenProject == null) return text;
StringBuilder res = new StringBuilder();
try {
doFilterText(PATTERN, manager, mavenProject, text, collectPropertiesFromDOM(mavenProject, projectDom), null, false, null, res);
}
catch (IOException e) {
throw new RuntimeException(e); // never thrown
}
return res.toString();
}
private static Properties collectPropertiesFromDOM(MavenProject project, MavenDomProjectModel projectDom) {
Properties result = new Properties();
collectPropertiesFromDOM(projectDom.getProperties(), result);
Collection<String> activeProfiles = project.getActivatedProfilesIds().getEnabledProfiles();
for (MavenDomProfile each : projectDom.getProfiles().getProfiles()) {
XmlTag idTag = each.getId().getXmlTag();
if (idTag == null || !activeProfiles.contains(idTag.getValue().getTrimmedText())) continue;
collectPropertiesFromDOM(each.getProperties(), result);
}
return result;
}
private static void collectPropertiesFromDOM(MavenDomProperties props, Properties result) {
XmlTag propsTag = props.getXmlTag();
if (propsTag != null) {
for (XmlTag each : propsTag.getSubTags()) {
result.setProperty(each.getName(), each.getValue().getTrimmedText());
}
}
}
@Nullable
private static String doResolveProperty(String propName,
MavenProjectsManager projectsManager,
MavenProject mavenProject,
Properties additionalProperties) {
boolean hasPrefix = false;
String unprefixed = propName;
if (propName.startsWith("pom.")) {
unprefixed = propName.substring("pom.".length());
hasPrefix = true;
}
else if (propName.startsWith("project.")) {
unprefixed = propName.substring("project.".length());
hasPrefix = true;
}
MavenProject selectedProject = mavenProject;
while (unprefixed.startsWith("parent.")) {
MavenId parentId = selectedProject.getParentId();
if (parentId == null) return null;
unprefixed = unprefixed.substring("parent.".length());
if (unprefixed.equals("groupId")) {
return parentId.getGroupId();
}
if (unprefixed.equals("artifactId")) {
return parentId.getArtifactId();
}
if (unprefixed.equals("version")) {
return parentId.getVersion();
}
selectedProject = projectsManager.findProject(parentId);
if (selectedProject == null) return null;
}
if (unprefixed.equals("basedir") || (hasPrefix && mavenProject == selectedProject && unprefixed.equals("baseUri"))) {
return selectedProject.getDirectory();
}
if ("java.home".equals(propName)) {
String jreDir = MavenUtil.getModuleJreHome(projectsManager, mavenProject);
if (jreDir != null) {
return jreDir;
}
}
if ("java.version".equals(propName)) {
String javaVersion = MavenUtil.getModuleJavaVersion(projectsManager, mavenProject);
if (javaVersion != null) {
return javaVersion;
}
}
String result;
result = MavenUtil.getPropertiesFromMavenOpts().get(propName);
if (result != null) return result;
result = MavenServerUtil.collectSystemProperties().getProperty(propName);
if (result != null) return result;
result = selectedProject.getModelMap().get(unprefixed);
if (result != null) return result;
result = additionalProperties.getProperty(propName);
if (result != null) return result;
result = mavenProject.getProperties().getProperty(propName);
if (result != null) return result;
if ("settings.localRepository".equals(propName)) {
return mavenProject.getLocalRepository().getAbsolutePath();
}
return null;
}
}