/*******************************************************************************
* Copyright (c) 2004, 2006
* Thomas Hallgren, Kenneth Olwing, Mitch Sonies
* Pontus Rydin, Nils Unden, Peer Torngren
* The code, documentation and other materials contained herein have been
* licensed under the Eclipse Public License - v 1.0 by the individual
* copyright holders listed above, as Initial Contributors under such license.
* The text of such license is available at www.eclipse.org.
*******************************************************************************/
package org.eclipse.buckminster.cvspkg.scheme.cvspkg;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Map;
import org.eclipse.buckminster.core.CorePlugin;
import org.eclipse.buckminster.core.common.model.Format;
import org.eclipse.buckminster.core.ctype.IComponentType;
import org.eclipse.buckminster.core.helpers.AccessibleByteArrayOutputStream;
import org.eclipse.buckminster.core.helpers.FileUtils;
import org.eclipse.buckminster.core.query.builder.ComponentQueryBuilder;
import org.eclipse.buckminster.core.reader.ICatalogReader;
import org.eclipse.buckminster.core.reader.IComponentReader;
import org.eclipse.buckminster.core.reader.IReaderType;
import org.eclipse.buckminster.core.reader.IStreamConsumer;
import org.eclipse.buckminster.core.resolver.ResolutionContext;
import org.eclipse.buckminster.core.rmap.model.Provider;
import org.eclipse.buckminster.core.version.VersionMatch;
import org.eclipse.buckminster.core.version.VersionSelector;
import org.eclipse.buckminster.cvspkg.Messages;
import org.eclipse.buckminster.runtime.URLUtils;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.osgi.util.NLS;
import org.osgi.service.url.AbstractURLStreamHandlerService;
/**
* Provides access to single files in a CVS repository using a URL. The URL must
* be formatted in the following way:
*
* <pre>
*
* cvs://[user@]<host>/<path to file>?repository=<repository path>[protocol=<cvs protocol>][#<tag>]
*
* </pre>
*
* @author Thomas Hallgren
*/
public class Handler extends AbstractURLStreamHandlerService {
class CVSConnection extends URLConnection {
private ICatalogReader reader;
private String fileName;
protected CVSConnection(URL entryURL) {
super(entryURL);
}
@Override
public void connect() throws IOException {
if (connected)
return;
try {
URI uri = this.getURL().toURI();
Map<String, String> params = URLUtils.queryAsParameters(uri.getQuery());
String host = uri.getHost();
if (host == null)
throw new MalformedURLException(Messages.cvs_URL_host_cannot_be_empty);
String rootStr = uri.getPath();
if (rootStr == null)
throw new MalformedURLException(Messages.cvs_URL_path_cannot_be_empty);
IPath rootPath = new Path(rootStr);
if (!rootPath.isAbsolute())
throw new MalformedURLException(Messages.cvs_URL_path_must_be_absolute);
if (rootPath.segmentCount() < 1)
throw new MalformedURLException(Messages.cvs_URL_path_must_have_segment);
if (rootPath.hasTrailingSeparator())
throw new MalformedURLException(Messages.cvs_URL_path_must_not_have_trailing_separator);
String moduleStr = uri.getFragment();
if (moduleStr == null)
throw new MalformedURLException(NLS.bind(Messages.cvs_URL_must_end_with_0, "#<" //$NON-NLS-1$
+ Messages.cvs_URL_module_path + ">")); //$NON-NLS-1$
IPath modulePath = new Path(moduleStr);
if (!modulePath.isAbsolute())
throw new MalformedURLException(Messages.cvs_URL_module_must_be_absolute);
if (modulePath.segmentCount() < 1)
throw new MalformedURLException(Messages.cvs_URL_module_must_have_segment);
if (modulePath.hasTrailingSeparator())
throw new MalformedURLException(Messages.cvs_URL_module_must_not_have_trailing_separator);
String user = uri.getUserInfo();
if (user == null)
user = "anonymous"; //$NON-NLS-1$
String cvsProto = params.get("method"); //$NON-NLS-1$
if (cvsProto == null)
cvsProto = "pserver"; //$NON-NLS-1$
fileName = modulePath.lastSegment();
modulePath = modulePath.removeLastSegments(1);
StringBuilder bld = new StringBuilder();
bld.append(':');
bld.append(cvsProto);
bld.append(':');
bld.append(user);
bld.append('@');
bld.append(host);
bld.append(':');
bld.append(rootPath.toPortableString());
if (modulePath.segmentCount() > 0) {
bld.append(',');
bld.append(modulePath.toPortableString());
}
CorePlugin plugin = CorePlugin.getDefault();
String versionSelector = params.get("version"); //$NON-NLS-1$
IReaderType cvsReaderType = plugin.getReaderType("cvs"); //$NON-NLS-1$
VersionMatch vm = versionSelector == null ? null
: new VersionMatch(null, VersionSelector.fromString(versionSelector), -1, null, null);
IProgressMonitor nullMon = new NullProgressMonitor();
Provider provider = new Provider(null,
"cvs", new String[] { IComponentType.UNKNOWN }, null, new Format(bld.toString()), null, null, null, null, null, null); //$NON-NLS-1$
ComponentQueryBuilder cqBld = new ComponentQueryBuilder();
cqBld.getRootRequestBuilder().setName(fileName);
if (vm == null)
vm = VersionMatch.DEFAULT;
reader = (ICatalogReader) cvsReaderType.getReader(provider, plugin.getComponentType(IComponentType.UNKNOWN), new ResolutionContext(
cqBld.createComponentQuery()).getRootNodeQuery(), vm, nullMon);
} catch (URISyntaxException e) {
throw new MalformedURLException(e.getMessage());
} catch (IllegalArgumentException e) {
throw new MalformedURLException(e.getMessage());
} catch (IOException e) {
throw e;
} catch (Exception e) {
Throwable t = e.getCause();
if (t instanceof IOException)
throw (IOException) t;
throw new IOException(e.getMessage());
}
connected = true;
}
@Override
public InputStream getInputStream() throws IOException {
this.connect();
try {
return reader.readFile(fileName, new IStreamConsumer<InputStream>() {
@Override
public InputStream consumeStream(IComponentReader componentReader, String streamName, InputStream stream, IProgressMonitor monitor)
throws IOException {
final AccessibleByteArrayOutputStream builder = new AccessibleByteArrayOutputStream();
FileUtils.copyFile(stream, builder, monitor);
return new FilterInputStream(builder.getInputStream()) {
@Override
public void close() throws IOException {
try {
super.close();
} finally {
reader.close();
}
}
};
}
}, new NullProgressMonitor());
} catch (CoreException e) {
Throwable t = e.getCause();
if (t instanceof IOException)
throw (IOException) t;
throw new IOException(e.getMessage());
}
}
}
public static final String PROTOCOL = "cvs"; //$NON-NLS-1$
@Override
public URLConnection openConnection(URL url) throws IOException {
return new CVSConnection(url);
}
}