krysalis-update/src/java/org/krysalis/depot/update/ant/cache RepositoryElement.java,NONE,1.1 CachedArtifactSet.java,NONE,1.1 CachedArtifactSetExportTask.java,NONE,1.1 CachedArtifactFileSet.java,NONE,1.1 ArtifactElement.java,NONE,1.1

Nick Chalko <[email protected]> Wed, 08 Dec 2004 09:07:11 +0000
Newsgroups gmane.comp.krysalis.cvs
Message-ID <[email protected]>
Update of /cvsroot/krysalis/krysalis-update/src/java/org/krysalis/depot/update/ant/cache
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24726/src/java/org/krysalis/depot/update/ant/cache

Added Files:
	RepositoryElement.java CachedArtifactSet.java 
	CachedArtifactSetExportTask.java CachedArtifactFileSet.java 
	ArtifactElement.java 
Log Message:
Copied from the apache incubator.

--- NEW FILE: CachedArtifactSet.java ---
/*
 * ========================================================================
 * Copyright 2004 The Apache Software Foundation
 * 
 * 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.krysalis.depot.update.ant.cache;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.FileScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.DataType;
import org.krysalis.depot.common.ant.util.AntLogListener;
import org.krysalis.depot.common.log.Logger;
import org.krysalis.depot.update.AntUtils;
import org.krysalis.depot.update.ArtifactInstance;
import org.krysalis.depot.update.ArtifactUpdater;
import org.krysalis.depot.update.ArtifactUpdaterFactory;
import org.krysalis.depot.update.Repository;
import org.krysalis.depot.update.UpdateException;
import org.krysalis.depot.update.query.ArtifactResult;
import org.krysalis.depot.update.repository.DefaultRepository;
import org.krysalis.depot.update.repository.RepositorySet;
import org.krysalis.depot.update.util.io.ResolvedFile;

/**
 * A locally cached repository backed set of resources.
 * 
 * @version $Revision: 1.1 $
 */
public class CachedArtifactSet extends DataType {
	public static final String DEFAULT_LOCAL_REPOSITORY_DIR_NAME = "local-repository";

	public static final String LOCAL_REPOSITORY_ID = "local.repository";

	public static final String REPOSITORY_DIR_PROPERTY = "repository.dir";

	private final Project project;

	private String id;

	private final CachedArtifactFileSet fileSet = new CachedArtifactFileSet(
			this);

	private final List resourceList = new ArrayList();

	private ArtifactUpdater m_updater = null;

	private boolean isAlwaysCheckRemote = false;

	private boolean checkClassPath = true;

	/**
	 *  
	 */
	public CachedArtifactSet(Project project) {
		super();
		this.project = project;
	}

	/**
	 * @param resource
	 * @return Artifact
	 */
	public ArtifactElement createArtifact() {
		ArtifactElement resource = new ArtifactElement(project);
		resourceList.add(resource);
		return resource;
	}

	/**
	 * @return Returns the id.
	 */
	public String getId() {
		return id;
	}

	/**
	 * @param id
	 *            The id to set.
	 */
	public void setId(String id) {
		this.id = id;
		project.addReference(id + ".fileset", fileSet);
	}

	/**
	 * @return
	 */
	FileScanner getFileScanner() throws UpdateException {
		final DirectoryScanner scanner = new DirectoryScanner();

		// Set logging context..
		Logger logger = Logger.pushContext(new AntLogListener(this));

		try {
			scanner.setBasedir(getRepoDir());
			addArtifacts(scanner);
		} finally {
			Logger.popContext(logger);
		}

		return scanner;
	}

	/**
	 * @param scanner
	 */
	private void addArtifacts(DirectoryScanner scanner) throws UpdateException {
		for (Iterator i = resourceList.iterator(); i.hasNext();) {
			ArtifactElement r = (ArtifactElement) i.next();
			add(scanner, r);
		}
	}

	/**
	 * @param scanner
	 * @param r
	 */
	private void add(DirectoryScanner scanner, ArtifactElement r)
			throws UpdateException {
		log("Looking for " + r, Project.MSG_DEBUG);
		File f = getLocalFile(r);
		if (f != null) {
			String path = f.getAbsolutePath();
			String basepath = scanner.getBasedir().getAbsolutePath();
			if (path.startsWith(basepath)) {
				path = path.substring(basepath.length() + 1);
			}
			scanner.setIncludes(new String[] { path });
			scanner.scan();
		} else {
			throw new BuildException("Unable to find " + r);
		}
	}

	/**
	 * Find and download if needed a the best local cached copy of a file. First
	 * check if a compitable file is available locally. If not down load the
	 * best one available from the repository. And finally return the best
	 * compatible file.
	 * 
	 * @param r
	 *            resourceElement the ant element describeing the resouce to
	 *            find
	 * @return File null if a compatible file can't be found.
	 * @throws UpdateException
	 */
	private File getLocalFile(ArtifactElement r) throws UpdateException {
		// TODO respect the ant build.classpath property.
		File file = null;
		if (!isAlwaysCheckRemote) {
			file = getCachedFile(r);
		}
		if (file == null) {
			cacheFile(r);
		}
		file = getCachedFile(r);
		return file;
	}

	/**
	 * @param element
	 */
	private void cacheFile(ArtifactElement element) {
		try {
			ArtifactInstance artifactInstance = findBestRemoteArtifact(element);
			if (artifactInstance != null) {

				downLoadRemoteResult(artifactInstance, element.getIRepository());
			}
			return;
		} catch (Exception e) {
			throw new BuildException("Unable to get local copy of " + element,
					e);
		}
	}

	/**
	 * @param r
	 * @return
	 */
	ArtifactInstance findBestRemoteArtifact(ArtifactElement r) {
		return r.findBestRemoteArtifact();
	}

	/**
	 * @param r
	 */
	private File getCachedFile(ArtifactElement r) throws UpdateException {
		try {
			ArtifactResult res = query(r, getLocalRepository());
			if (res.size() == 0) {
				return null;
			} else if (res.size() == 1) {
				return getFirstFile(res);
			} else {
				log("Found " + res.size() + " matches for " + r
						+ " returning first", Project.MSG_VERBOSE);
				return getFirstFile(res);
			}
		} catch (Exception e) {
			throw new BuildException("Error trying to get local copy of " + r,
					e);
		}
	}

	/**
	 * @return
	 */
	private File getRepoDir() {
		// TODO cache this.
		File repo = AntUtils.findAndCreateDirFromProperty(getProject(),
				REPOSITORY_DIR_PROPERTY);
		if (repo == null) {
			repo = new File(AntUtils.getDepotHome(getProject()),
					DEFAULT_LOCAL_REPOSITORY_DIR_NAME);
		}
		AntUtils.createAndValidateDir(getProject(), repo,
				"Local Repository Cache", true);
		return repo;
	}

	/**
	 * Should the cached set always look the remore repository for updates
	 * 
	 * @return Returns the isAlwaysCheckRemote.
	 */
	public boolean isAlwaysCheckRemote() {
		return isAlwaysCheckRemote;
	}

	/**
	 * Should the cached set always look the remore repository for updates
	 * 
	 * @param isAlwaysCheckRemote
	 *            The isAlwaysCheckRemote to set.
	 */
	public void setAlwaysCheckRemote(boolean isAlwaysCheckRemote) {
		this.isAlwaysCheckRemote = isAlwaysCheckRemote;
	}

	/**
	 * @param r
	 * @param res
	 * @return
	 */
	private File getFirstFile(ArtifactResult res) throws Exception {
		ArtifactInstance instance = ArtifactResult.getFirstArtifact(res);
		return instance.getLocator().getLocation().getFile();
	}

	private ArtifactResult query(ArtifactElement r, Repository repo) {
		return r.query(repo);
	}

	/**
	 * @return
	 */
	private Repository getLocalRepository() {
		DefaultRepository repository = new DefaultRepository(
				LOCAL_REPOSITORY_ID, ResolvedFile.resolve(getRepoDir()));
		return repository;
	}

	/**
	 * @param repository
	 * @param resource
	 * @throws UpdateException
	 */
	private void downLoadRemoteResult(ArtifactInstance artifactInstance,
			Repository repository) throws UpdateException {
		ArtifactUpdater ru = ArtifactUpdaterFactory.getDefaultUpdater();
		ru.setTargetRepository(getLocalRepository());
		ru.setRepositorySet(new RepositorySet(repository.getIdentifier()
				+ " set", repository));
		ru.getInstance(artifactInstance.getArtifact()); // TODO are we doing
		// this twice?.
	}

	/**
	 * @return Returns the unmodifiableList of resources.
	 */
	List getArtifactList() {
		return Collections.unmodifiableList(resourceList);
	}
}
--- NEW FILE: ArtifactElement.java ---
/*
 * ========================================================================
 * Copyright 2004 The Apache Software Foundation
 * 
 * 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.krysalis.depot.update.ant.cache;
import java.io.File;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.DataType;
import org.krysalis.depot.update.Artifact;
import org.krysalis.depot.update.ArtifactInstance;
import org.krysalis.depot.update.Repository;
import org.krysalis.depot.update.UpdateException;
import org.krysalis.depot.update.artifact.ArtifactGroup;
import org.krysalis.depot.update.artifact.ArtifactLocator;
import org.krysalis.depot.update.artifact.ArtifactType;
import org.krysalis.depot.update.artifact.compare.VersionComparator;
import org.krysalis.depot.update.artifact.select.NameSelector;
import org.krysalis.depot.update.artifact.select.TypeSelector;
import org.krysalis.depot.update.artifact.select.VersionSelector;
import org.krysalis.depot.update.impl.ArtifactUpdaterContext;
import org.krysalis.depot.update.impl.RepositorySetWrapper;
import org.krysalis.depot.update.protocols.DefaultProtocolOperationsManager;
import org.krysalis.depot.update.query.ArtifactQuery;
import org.krysalis.depot.update.query.ArtifactResult;
import org.krysalis.depot.update.query.QueryEngine;
import org.krysalis.depot.update.repository.DefaultRepository;
import org.krysalis.depot.update.repository.RepositorySet;
import org.krysalis.depot.update.util.io.ResolvedFile;
import org.krysalis.depot.update.util.net.VirtualResourceLocator;
import org.krysalis.depot.update.util.select.ISelector;
import org.krysalis.depot.update.util.select.logic.AndSelector;
import org.krysalis.version.Version;
import org.krysalis.version.VersionException;
import org.krysalis.version.impl.apache.ApacheVersion;
/**
 * @version $Revision: 1.1 $
 */
public class ArtifactElement extends DataType {
	private String group;
	private String name;
	private String version;
	private String repository;
	private String ext;
	private ArtifactInstance bestRemoteArtifact;
	private final Project project;

	/**
	 * @return Returns the name.
	 */
	public String getName() {
		return name;
	}

	/**
	 * @param name
	 *            The name to set.
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * @return Returns the repository.
	 */
	public String getRepository() {
		return repository;
	}

	/**
	 * @param repository
	 *            The repository to set.
	 */
	public void setRepository(String repository) {
		this.repository = repository;
	}

	/**
	 * @return Returns the version.
	 */
	public String getVersion() {
		return version;
	}

	/**
	 * @param version
	 *            The version to set.
	 */
	public void setVersion(String version) {
		this.version = version;
	}

	/**
	 * @return Returns the ext.
	 */
	public String getExt() {
		return ext;
	}

	/**
	 * * The ext to set.
	 */
	public void setExt(String ext) {
		this.ext = ext;
	}

	public String toString() {
		return name + "-" + version + "." + ext + "@" + repository;
	}

	/**
	 * @return
	 */
	ArtifactInstance initArtifact() {
		ArtifactInstance r = new ArtifactInstance(
					new Artifact(getArtifactGroup(), name, getArtifactType(), getVersionObject()
						), 
						new ArtifactLocator(getFileName(),
						ext, getLocation()));
		return r;
	}

	/**
	 * @return
	 */
	private VirtualResourceLocator getLocation() {
		ResolvedFile rf = ResolvedFile.resolve(new File(getFileName()));
		VirtualResourceLocator vrl = new VirtualResourceLocator(rf);
		// TODO Auto-generated method stub
		return vrl;
	}

	/**
	 * @return
	 */
	private String getFileName() {
		// TODO Auto-generated method stub
		return getName() + "-" + getVersion() + "." + getExt();
	}

	/**
	 * @return
	 */
	ArtifactType getArtifactType() {
		return ArtifactType.JAVA_BINARY;// :TODO: fix
	}

	/**
	 * @return
	 */
	private Version getVersionObject() {
		// TODO Auto-generated method stub
		return null;
	}

	/**
	 * @return
	 */
	ArtifactGroup getArtifactGroup() {
		ArtifactGroup rg = new ArtifactGroup(group == null ? name : group);
		return rg;
	}

	/**
	 * @return Returns the group.
	 */
	public String getGroup() {
		return group;
	}

	/**
	 * @param group
	 *            The group to set.
	 */
	public void setGroup(String group) {
		this.group = group;
	}

	/**
	 * @return
	 */
	public TypeSelector getArtifactTypeSelector() {
		// TODO Auto-generated method stub
		return new TypeSelector(getArtifactType());
	}

	/**
	 * @return
	 */
	public Repository getIRepository() {
		RepositoryElement repositoryElement = (RepositoryElement) project.getReference(getRepository());
		return new DefaultRepository(repositoryElement.getId(),
				new VirtualResourceLocator(repositoryElement.getUrl()));
	}

	/**
	 *  
	 */
	public ArtifactElement(Project project) {
		super();
		this.project = project;
	}

	public ISelector getArtifactSelector() throws VersionException {
		AndSelector set = new AndSelector();
		set.addSelector(new NameSelector(name));
		set.addSelector(new TypeSelector(getArtifactType()));
		if (null != version) {
			set.addSelector(new VersionSelector( new ApacheVersion(version)));
		}
		return (ISelector) set;
	}

	/**
	 * @return
	 */
	public String getDownloadedFrom() {
		if (bestRemoteArtifact == null) {
			bestRemoteArtifact = findBestRemoteArtifact();
		}
		if (bestRemoteArtifact != null) {
			return bestRemoteArtifact.getLocator().getLocation().toExternalForm();
		} else {
			return null;
		}
	}

	/**
	 * @return
	 */
	public Version getDownloadedVersion() {
		if (bestRemoteArtifact == null) {
			bestRemoteArtifact = findBestRemoteArtifact();
		}
		if (bestRemoteArtifact != null) {
			return bestRemoteArtifact.getArtifact().getVersion();
		} else {
			return null;
		}
	}

	/**
	 * @param this
	 * @return
	 */
	ArtifactInstance findBestRemoteArtifact() {
		ArtifactResult res = query(getIRepository());
		ArtifactInstance resource = null;
		if (res.size() == 0) {
			resource = null;
		} else if (res.size() == 1) {
			resource = ArtifactResult.getFirstArtifact(res);
		} else {
			getProject().log(
					"Found " + res.size() + " matches for " + this
							+ " returning first", Project.MSG_VERBOSE);
			resource = ArtifactResult.getFirstArtifact(res);
		}
		bestRemoteArtifact = resource;
		return resource;
	}

	ArtifactResult query(Repository repo) { //TODO
		// experiment
		getProject().log("Looking for " + this, Project.MSG_DEBUG);
		try {
			QueryEngine dqe = new QueryEngine();
			ArtifactQuery query = new ArtifactQuery(getArtifactGroup(),
					getArtifactSelector(), null, VersionComparator.REVERSE);
			//TODO need to be a better way to sort by.
			ArtifactUpdaterContext context = new ArtifactUpdaterContext();
			context.setProtocolManager(new DefaultProtocolOperationsManager(
					context));
			RepositorySet repositorySet = RepositorySet.getRepositorySet(
					repo.getIdentifier().getId(), true);
			repositorySet.addRepository(repo);
			RepositorySetWrapper rw = new RepositorySetWrapper(repositorySet,
					context);
			ArtifactResult result = dqe.queryRepositories(rw, query);
			return result;
		} catch (VersionException e) {
			throw new BuildException("Unable to process " + this, e);
		} catch (UpdateException e) {
			throw new BuildException("Unable to get " + this, e);
		}
	}
}
--- NEW FILE: CachedArtifactFileSet.java ---
/*
 * ========================================================================
 * Copyright 2004 The Apache Software Foundation
 * 
 * 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.krysalis.depot.update.ant.cache;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.FileScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.FileSet;
/**
 *  
 */
final class CachedArtifactFileSet extends FileSet {
	private final CachedArtifactSet updateSet;
	private boolean initialized = false;
	private FileScanner scanner;
	CachedArtifactFileSet(CachedArtifactSet updateSet) {
		this.updateSet = updateSet;
	}
	private synchronized void initialize() {
		if (!initialized) {
			try {
				scanner = updateSet.getFileScanner();
				scanner.getIncludedFiles();
				setDir(scanner.getBasedir());
				setupDirectoryScanner(scanner, updateSet.getProject());
			} catch (BuildException e) {
				throw e;
			} catch (Exception e) {
				throw new BuildException("error initializing " + getDataTypeName(), e);
			}
		}
		initialized = true;
	}
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.apache.tools.ant.types.AbstractFileSet#getDirectoryScanner(org.apache.tools.ant.Project)
	 */
	public DirectoryScanner getDirectoryScanner(Project p) {
		initIfNeeded();
		return super.getDirectoryScanner(p);
	}
	/**
	 *  
	 */
	private void initIfNeeded() {
		if (!initialized) {
			initialize();
		}
	}
}
--- NEW FILE: RepositoryElement.java ---
/* ========================================================================
 * Copyright 2004 The Apache Software Foundation
 *
 *    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.krysalis.depot.update.ant.cache;

import java.net.URL;

import org.apache.tools.ant.types.DataType;

 
/**
 * Describes a Repository for use in other Depot Ant tasks.
 *  @version $Revision: 1.1 $
 */
public class RepositoryElement extends DataType {
	

	private URL url;
	private boolean remote;
	private String id;

	/**
	 * @return Returns the remote.
	 */
	public boolean isRemote() {
		return remote;
		
	}
	/**
	 * @param remote The remote to set.
	 */
	public void setRemote(boolean remote) {
		this.remote = remote;
	}
	/**
	 * @return Returns the url.
	 */
	public URL getUrl() {
		return url;
	}
	/**
	 * @param url The url to set.
	 */
	public void setUrl(URL url) {
		this.url = url;
	}
	/**
	 * @return Returns the id.
	 */
	public String getId() {
		return id;
	}
	/**
	 * @param id The id to set.
	 */
	public void setId(String id) {
		this.id = id;		
	}
}

--- NEW FILE: CachedArtifactSetExportTask.java ---
/*
 * ========================================================================
 * Copyright 2004 The Apache Software Foundation
 * 
 * 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.krysalis.depot.update.ant.cache;
import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.Iterator;
import java.util.List;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
/**
 * Export a cached resource set to xml file. <code>
 * <cachedresourceset>
 *      <resource name="foo" 
 *                version="1.2.3"  
 *                href="http://mydownload.com/bar/foo-1.2.3.jar" 
 *                local="${local.repository}/bar/jars/foo-1.2.3.jar"/>
 * </cachedresourceset>
 * </code>
 */
public class CachedArtifactSetExportTask extends Task {
	private String refid;
	private File toFile;
	/**
	 * The refid of the cachedset to export.
	 * 
	 * @return Returns the refid.
	 */
	public String getRefid() {
		return refid;
	}
	/**
	 * SEt the refid of the cachedset to export
	 * 
	 * @param refid
	 *            The refid to set.
	 */
	public void setRefid(String refid) {
		this.refid = refid;
	}
	/**
	 * The file to export the Cached set to
	 * 
	 * @return Returns the toFile.
	 */
	public File getToFile() {
		return toFile;
	}
	/**
	 * The file to export the Cached set to
	 * 
	 * @param toFile
	 *            The toFile to set.
	 */
	public void setToFile(File toFile) {
		this.toFile = toFile;
	}
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.apache.tools.ant.Task#execute()
	 */
	public void execute() throws BuildException {
		try {
			CachedArtifactSet cachedArtifactSet = (CachedArtifactSet) getProject()
					.getReference(getRefid());
			// TODO use real XML stuff
			// njc Feeling lazy tonight
			Writer writer = new FileWriter(getToFile());
			PrintWriter out = new PrintWriter(writer);
			List resourceList = cachedArtifactSet.getArtifactList();
			out.println("<?xml " + nameValue("version", "1.0") + "?>");
			out
					.println("<!DOCTYPE cachedartifactset PUBLIC \"-//APACHE//DTD CachedArtifact V0.1//EN\" \"http://incubator.apache.org/depot/dtd/cachedartifact-v01.dtd\">");
			out.println("<cachedartifactset " + nameValue("id", getRefid())
					+ ">");
			for (Iterator i = resourceList.iterator(); i.hasNext();) {
				ArtifactElement resource = (ArtifactElement) i.next();
				out.println("    <artifact "
						+ nameValue("name", resource.getName()));
				out.println("              "
						+ nameValue("group", resource.getGroup() == null
								? resource.getName()
								: resource.getGroup()));
				org.krysalis.version.Version version = resource.getDownloadedVersion();
				if (version == null) {
					version = org.krysalis.version.Version.UNKNOWN;
				}
			
				out.println("              "
						+ nameValue("version", version.toString()));
				out.println("              "
						+ nameValue("href", resource.getDownloadedFrom()));
				out.println("     />");
				log(resource + "  from  " + resource.getDownloadedFrom());
			}
			out.println("</cachedartifactset>");
			out.close();
			writer.close();
		} catch (Exception e) {
			throw new BuildException("Error exporting cached resource set "
					+ getRefid(), e);
		}
	}
	private String nameValue(final String name, final String value) {
		String togther = name + "=\"" + value + "\"";
		return togther;
	}
}


-------------------------------------------------------
SF email is sponsored by - The IT Product Guide
Read honest & candid reviews on hundreds of IT Products from real users.
Discover which products truly live up to the hype. Start reading now. 
http://productguide.itmanagersjournal.com/