blob: 2331d7e20cc68c5193743c39716272bee3fe81c4 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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
*
* https://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.apache.ivy.ant;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.ParseException;
import java.util.Properties;
import org.apache.ivy.Ivy;
import org.apache.ivy.core.settings.IvySettings;
import org.apache.ivy.core.settings.IvyVariableContainer;
import org.apache.ivy.util.Message;
import org.apache.ivy.util.url.CredentialsStore;
import org.apache.ivy.util.url.TimeoutConstrainedURLHandler;
import org.apache.ivy.util.url.URLHandlerDispatcher;
import org.apache.ivy.util.url.URLHandlerRegistry;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.ProjectComponent;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.taskdefs.Property;
import org.apache.tools.ant.types.DataType;
import static org.apache.ivy.util.StringUtils.isNullOrEmpty;
public class IvyAntSettings extends DataType {
public static class Credentials {
private String realm;
private String host;
private String username;
private String passwd;
public String getPasswd() {
return this.passwd;
}
public void setPasswd(String passwd) {
this.passwd = passwd;
}
public String getRealm() {
return this.realm;
}
public void setRealm(String realm) {
this.realm = format(realm);
}
public String getHost() {
return this.host;
}
public void setHost(String host) {
this.host = format(host);
}
public String getUsername() {
return this.username;
}
public void setUsername(String userName) {
this.username = format(userName);
}
}
private Ivy ivyEngine = null;
private File file = null;
private URL url = null;
private String realm = null;
private String host = null;
private String userName = null;
private String passwd = null;
private String id = "ivy.instance";
private boolean autoRegistered = false;
private AntWorkspaceResolver antWorkspaceResolver;
/**
* Returns the default ivy settings of this classloader. If it doesn't exist yet, a new one is
* created using the given project to back the VariableContainer.
*
* @param task
* TODO add text.
* @return An IvySetting instance.
*/
public static IvyAntSettings getDefaultInstance(ProjectComponent task) {
Project project = task.getProject();
Object defaultInstanceObj = project.getReference("ivy.instance");
if (defaultInstanceObj != null
&& defaultInstanceObj.getClass().getClassLoader() != IvyAntSettings.class
.getClassLoader()) {
task.log("ivy.instance reference an ivy:settings defined in an other classloader. "
+ "An new default one will be used in this project.", Project.MSG_WARN);
defaultInstanceObj = null;
}
if (defaultInstanceObj != null && !(defaultInstanceObj instanceof IvyAntSettings)) {
throw new BuildException("ivy.instance reference a "
+ defaultInstanceObj.getClass().getName()
+ " an not an IvyAntSettings. Please don't use this reference id ()");
}
if (defaultInstanceObj == null) {
task.log("No ivy:settings found for the default reference 'ivy.instance'. "
+ "A default instance will be used", Project.MSG_VERBOSE);
IvyAntSettings settings = new IvyAntSettings();
settings.setProject(project);
project.addReference("ivy.instance", settings);
settings.createIvyEngine(task);
return settings;
} else {
return (IvyAntSettings) defaultInstanceObj;
}
}
/*
* Keep this for backwards compatibility!
*/
public static IvyAntSettings getDefaultInstance(Task task) {
return getDefaultInstance((ProjectComponent) task);
}
public File getFile() {
return file;
}
public URL getUrl() {
return url;
}
public String getPasswd() {
return passwd;
}
public void setPasswd(String aPasswd) {
passwd = aPasswd;
}
public String getRealm() {
return realm;
}
public void setRealm(String aRealm) {
realm = format(aRealm);
}
public String getHost() {
return host;
}
public void setHost(String aHost) {
host = format(aHost);
}
public String getUsername() {
return userName;
}
public void setUsername(String aUserName) {
userName = format(aUserName);
}
public void setProject(Project p) {
super.setProject(p);
if ("ivy.instance".equals(id) && !getProject().getReferences().containsKey(id)) {
// register ourselves as default settings, just in case the id attribute is not set
getProject().addReference("ivy.instance", this);
autoRegistered = true;
}
}
private static String format(String str) {
return isNullOrEmpty(str) ? null : str.trim();
}
public void addConfiguredCredentials(Credentials c) {
CredentialsStore.INSTANCE.addCredentials(c.getRealm(), c.getHost(), c.getUsername(),
c.getPasswd());
}
public void setFile(File file) {
this.file = file;
}
public void setUrl(String confUrl) throws MalformedURLException {
this.url = new URL(confUrl);
}
public void setUrl(URL url) {
this.url = url;
}
/*
* This is usually not necessary to define a reference in Ant, but it's the only way to know the
* id of the settings, which we use to set ant properties.
*/
public void setId(String id) {
if (autoRegistered && getProject().getReference(this.id) == this) {
getProject().getReferences().remove(this.id);
autoRegistered = false;
}
this.id = id;
if (getProject() != null) {
getProject().addReference(this.id, this);
}
}
public String getId() {
return id;
}
/**
* Return the configured Ivy instance.
*
* @param task ProjectComponent
* @return Returns the configured Ivy instance.
*/
public Ivy getConfiguredIvyInstance(ProjectComponent task) {
if (ivyEngine == null) {
createIvyEngine(task);
}
return ivyEngine;
}
/*
* Keep this for backwards compatibility!
*/
public Ivy getConfiguredIvyInstance(Task task) {
return getConfiguredIvyInstance((ProjectComponent) task);
}
void createIvyEngine(final ProjectComponent task) {
Project project = task.getProject();
Property prop = new Property() {
public void execute() throws BuildException {
addProperties(getDefaultProperties(task));
}
};
prop.setProject(project);
prop.init();
prop.execute();
IvyAntVariableContainer ivyAntVariableContainer = new IvyAntVariableContainer(project);
IvySettings settings = new IvySettings(ivyAntVariableContainer);
settings.setBaseDir(project.getBaseDir());
if (file == null && url == null) {
defineDefaultSettingFile(ivyAntVariableContainer, task);
}
if (antWorkspaceResolver != null) {
settings.addConfigured(antWorkspaceResolver.getResolver());
}
Ivy ivy = Ivy.newInstance(settings);
try {
ivy.pushContext();
AntMessageLogger.register(task, ivy);
Message.showInfo();
configureURLHandler();
if (file != null) {
if (!file.exists()) {
throw new BuildException("settings file does not exist: " + file);
}
ivy.configure(file);
} else {
if (url == null) {
throw new AssertionError(
"ivy setting should have either a file, either an url,"
+ " and if not defineDefaultSettingFile must set it.");
}
ivy.configure(url);
}
ivyAntVariableContainer.updateProject(id);
ivyEngine = ivy;
} catch (ParseException | IOException e) {
throw new BuildException("impossible to configure ivy:settings with given "
+ (file != null ? "file: " + file : "url: " + url) + " : " + e, e);
} finally {
ivy.popContext();
}
}
protected Properties getDefaultProperties(ProjectComponent task) {
URL url = IvySettings.getDefaultPropertiesURL();
// this is copy of loadURL code from ant Property task (not available in 1.5.1)
Properties props = new Properties();
task.log("Loading " + url, Project.MSG_VERBOSE);
try (InputStream is = url.openStream()) {
props.load(is);
} catch (IOException ex) {
throw new BuildException(ex);
}
return props;
}
/**
* Set file or url to its default value
*
* @param variableContainer IvyVariableContainer
*/
private void defineDefaultSettingFile(IvyVariableContainer variableContainer,
ProjectComponent task) {
String settingsFileName = variableContainer.getVariable("ivy.conf.file");
if (settingsFileName != null
&& !settingsFileName.equals(variableContainer.getVariable("ivy.settings.file"))) {
task.log("DEPRECATED: 'ivy.conf.file' is deprecated, use 'ivy.settings.file' instead",
Project.MSG_INFO);
} else {
settingsFileName = variableContainer.getVariable("ivy.settings.file");
}
File[] settingsLocations = new File[] {
new File(getProject().getBaseDir(), settingsFileName),
new File(getProject().getBaseDir(), "ivyconf.xml"), new File(settingsFileName),
new File("ivyconf.xml")};
for (File settingsFile : settingsLocations) {
task.log("searching settings file: trying " + settingsFile, Project.MSG_VERBOSE);
if (settingsFile.exists()) {
file = settingsFile;
break;
}
}
if (file == null) {
if (Boolean.valueOf(getProject().getProperty("ivy.14.compatible"))) {
task.log("no settings file found, using Ivy 1.4 default...", Project.MSG_VERBOSE);
url = IvySettings.getDefault14SettingsURL();
} else {
String settingsFileUrl = variableContainer.getVariable("ivy.settings.url");
if (settingsFileUrl != null) {
try {
url = new URL(settingsFileUrl);
} catch (MalformedURLException e) {
throw new BuildException(
"Impossible to configure ivy:settings with given url: "
+ settingsFileUrl + ": " + e.getMessage(), e);
}
} else {
task.log("no settings file found, using default...", Project.MSG_VERBOSE);
url = IvySettings.getDefaultSettingsURL();
}
}
}
}
private void configureURLHandler() {
// TODO : the credentialStore should also be scoped
CredentialsStore.INSTANCE.addCredentials(getRealm(), getHost(), getUsername(), getPasswd());
URLHandlerDispatcher dispatcher = new URLHandlerDispatcher();
TimeoutConstrainedURLHandler httpHandler = URLHandlerRegistry.getHttp();
dispatcher.setDownloader("http", httpHandler);
dispatcher.setDownloader("https", httpHandler);
URLHandlerRegistry.setDefault(dispatcher);
}
public void addConfiguredWorkspaceResolver(AntWorkspaceResolver antWorkspaceResolver) {
this.antWorkspaceResolver = antWorkspaceResolver;
}
}