/*
* eXist Open Source Native XML Database
* Copyright (C) 2006-2007 The eXist Project
* http://exist-db.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $Id$
*/
package org.exist.xmldb;
import java.net.URI;
import java.net.URISyntaxException;
public class FullXmldbURI extends XmldbURI {
//this will never have xmldb:
private URI wrappedURI;
private String context;
private String apiName;
/**
* Contructs an XmldbURI from given URI.
* The provided URI must have the XMLDB_SCHEME ("xmldb")
* @param xmldbURI A string
* @throws URISyntaxException If the given string is not a valid xmldb URI.
*/
protected FullXmldbURI(URI xmldbURI) throws URISyntaxException {
super(xmldbURI);
}
/** Feeds private members
* @throws URISyntaxException
*/
protected void parseURI(URI xmldbURI, boolean hadXmldbPrefix) throws URISyntaxException {
wrappedURI = xmldbURI;
if(hadXmldbPrefix) {
if (wrappedURI.getScheme() == null)
//Put the "right" URI in the message ;-)
throw new URISyntaxException(XMLDB_URI_PREFIX+wrappedURI.toString(), "xmldb URI scheme has no instance name");
String userInfo = wrappedURI.getUserInfo();
//Very tricky :
if (wrappedURI.getHost() == null && wrappedURI.getAuthority() != null) {
userInfo = wrappedURI.getAuthority();
if (userInfo.endsWith("@"))
userInfo = userInfo.substring(0, userInfo.length() - 1);
}
//Eventually rewrite wrappedURI *without* user info
if (userInfo != null) {
StringBuilder recomputed = new StringBuilder();//XMLDB_URI_PREFIX);
recomputed.append(wrappedURI.getScheme());
recomputed.append("://");
recomputed.append(wrappedURI.getHost());
if (wrappedURI.getPort() != -1)
recomputed.append(":").append(wrappedURI.getPort());
recomputed.append(wrappedURI.getRawPath());
wrappedURI = new URI(recomputed.toString());
}
}
super.parseURI(xmldbURI,hadXmldbPrefix);
}
protected void splitPath(String path) throws URISyntaxException {
int index = -1;
int lastIndex = -1;
//Reinitialise members
this.context = null;
String pathForSuper = null;
if (path != null) {
String host = getHost();
if(host==null || EMBEDDED_SERVER_AUTHORITY.equals(host)) {
if (getPort() != NO_PORT)
//Put the "right" URI in the message ;-)
throw new URISyntaxException(XMLDB_URI_PREFIX+wrappedURI.toString(), "Local xmldb URI should not provide a port");
apiName = API_LOCAL;
context = null;
pathForSuper = path;
} else {
//Try to extract the protocol from the provided URI.
//TODO : get rid of this and use a more robust approach (dedicated constructor ?) -pb
//TODO : use named constants
index = path.lastIndexOf("/xmlrpc");
if (index > lastIndex) {
apiName = API_XMLRPC;
pathForSuper = path.substring(index + "/xmlrpc".length());
context = path.substring(0, index) + "/xmlrpc";
lastIndex = index;
}
//TODO : use named constants
index = path.lastIndexOf("/webdav");
if (index > lastIndex) {
apiName = API_WEBDAV;
pathForSuper = path.substring(index + "/webdav".length());
context = path.substring(0, index) + "/webdav";
lastIndex = index;
}
//Default : REST-style...
if (apiName == null) {
apiName = API_REST;
pathForSuper = path;
//TODO : determine the context out of a clean root collection policy.
context = null;
}
}
}
super.splitPath(pathForSuper);
}
/** To be called each time a private member that interacts with the wrapped URI is modified.
* @throws URISyntaxException
*/
protected void recomputeURI() throws URISyntaxException {
URI oldWrappedURI = wrappedURI;
StringBuilder buf = new StringBuilder();
if (getInstanceName() != null)
buf.append(getInstanceName()).append("://");
//No userInfo
if (getHost() != null)
buf.append(getHost());
if (getPort() != NO_PORT)
buf.append(":" + getPort());
if (context != null)
buf.append(context);
//TODO : eventually use a prepend.root.collection system property
if (getRawCollectionPath() != null)
buf.append(getRawCollectionPath());
try {
wrappedURI = new URI(buf.toString());
} catch (URISyntaxException e) {
wrappedURI = oldWrappedURI;
throw e;
}
}
private void setContext(String context) {
String oldContext = this.context;
try {
//trims any trailing slash
if (context != null && context.endsWith("/")) {
//include root slash if we have a host
if (this.getHost() != null)
context = context.substring(0, context.length() - 1);
}
this.context = "".equals(context) ? null : context;
recomputeURI();
} catch (URISyntaxException e) {
this.context = oldContext;
throw new IllegalArgumentException("Invalid URI: "+e.getMessage());
}
}
public URI getURI() {
return wrappedURI;
}
public URI getXmldbURI() {
return URI.create(XMLDB_URI_PREFIX+wrappedURI.toString());
}
public String getInstanceName() {
return wrappedURI.getScheme();
}
public String getApiName() {
return apiName;
}
public String getContext() {
return context;
}
public boolean isAbsolute() {
return wrappedURI.isAbsolute();
}
public boolean isContextAbsolute() {
String context = this.getContext();
if (context == null)
return true;
return context.startsWith("/");
}
public XmldbURI normalizeContext() {
String context = this.getContext();
if (context == null)
return this;
URI uri = URI.create(context);
try {
FullXmldbURI xmldbURI = new FullXmldbURI(getXmldbURI());
xmldbURI.setContext(uri.normalize().getRawPath());
return xmldbURI;
} catch (URISyntaxException e) {
throw new IllegalArgumentException("Invalid URI: "+e.getMessage());
}
}
public URI relativizeContext(URI uri) {
if (uri == null)
throw new NullPointerException("The provided URI is null");
String context = this.getContext();
if (context == null)
throw new NullPointerException("The current context is null");
URI contextURI;
//Adds a final slash if necessary
if (!context.endsWith("/")) {
LOG.info("Added a final '/' to '" + context + "'");
contextURI = URI.create(context + "/");
} else
contextURI = URI.create(context);
return contextURI.relativize(uri);
}
public URI resolveContext(String str) throws NullPointerException, IllegalArgumentException {
if (str == null)
throw new NullPointerException("The provided URI is null");
String context = this.getContext();
if (context == null)
throw new NullPointerException("The current context is null");
URI contextURI;
//Adds a final slash if necessary
if (!context.endsWith("/")) {
LOG.info("Added a final '/' to '" + context + "'");
contextURI = URI.create(context + "/");
} else
contextURI = URI.create(context);
return contextURI.resolve(str);
}
public URI resolveContext(URI uri) throws NullPointerException {
if (uri == null)
throw new NullPointerException("The provided URI is null");
String context = this.getContext();
if (context == null)
throw new NullPointerException("The current context is null");
URI contextURI;
//Adds a final slash if necessary
if (!context.endsWith("/")) {
LOG.info("Added a final '/' to '" + context + "'");
contextURI = URI.create(context + "/");
} else
contextURI = URI.create(context);
return contextURI.resolve(uri);
}
public String toString() {
return XMLDB_URI_PREFIX + wrappedURI.toString();
}
/* (non-Javadoc)
* @see java.net.URI#getAuthority()
*/
public String getAuthority() {
return wrappedURI.getAuthority();
}
/* (non-Javadoc)
* @see java.net.URI#getFragment()
*/
public String getFragment() {
return wrappedURI.getFragment();
}
/* (non-Javadoc)
* @see java.net.URI#getPort()
*/
public int getPort() {
return wrappedURI.getPort();
}
/* (non-Javadoc)
* @see java.net.URI#getQuery()
*/
public String getQuery() {
return wrappedURI.getQuery();
}
/* (non-Javadoc)
* @see java.net.URI#getRawAuthority()
*/
public String getRawAuthority() {
return wrappedURI.getRawAuthority();
}
/* (non-Javadoc)
* @see java.net.URI#getHost()
*/
public String getHost() {
return wrappedURI.getHost();
}
/* (non-Javadoc)
* @see java.net.URI#getUserInfo()
*/
public String getUserInfo() {
return wrappedURI.getUserInfo();
}
/* (non-Javadoc)
* @see java.net.URI#getRawFragment()
*/
public String getRawFragment() {
return wrappedURI.getRawFragment();
}
/* (non-Javadoc)
* @see java.net.URI#getRawQuery()
*/
public String getRawQuery() {
return wrappedURI.getRawQuery();
}
/* (non-Javadoc)
* @see java.net.URI#getRawUserInfo()
*/
public String getRawUserInfo() {
return wrappedURI.getRawUserInfo();
}
}