* @param request the request.
*
* @return the response target.
*/
public Target resolve(Request request) {
RequestContext context = (RequestContext) request;
final ServletRequestContext requestContext;
if (context instanceof ServletRequestContext) {
requestContext = (ServletRequestContext) request;
} else {
requestContext = null;
}
if (embeddedRegistryService == null) {
if (requestContext != null) {
embeddedRegistryService =
(EmbeddedRegistryService) requestContext.getRequest().getSession()
.getServletContext().getAttribute("registry");
}
if (embeddedRegistryService == null) {
String msg = "Error in retrieving the embedded registry service.";
log.error(msg);
}
}
//TODO (reg-sep)
UserRegistry registry = null;
String uri = context.getUri().toString();
String loggedIn = null;
if (requestContext != null) {
loggedIn = ((ServletRequestContext) request).getRequest().getParameter("loggedIn");
}
if (loggedIn != null) {
String loggedUser =
(String) requestContext.getRequest().getSession().getServletContext()
.getAttribute("logged-user");
try {
registry = embeddedRegistryService.getRegistry(loggedUser);
uri = uri.substring(0, uri.lastIndexOf("?"));
} catch (RegistryException e) {
final StringResponseContext response =
new StringResponseContext("Unauthorized", 401);
response.setHeader("WWW-Authenticate", "Basic realm=\"WSO2-Registry\"");
return new ResponseTarget(context, response);
}
}
if (registry == null) {
// Set up secure registry instance
String authorizationString = request.getAuthorization();
if (authorizationString != null) {
// splitting the Authorization string "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="
String values[] = authorizationString.split("\\ ");
if (values == null || values.length == 0) {
final StringResponseContext response =
new StringResponseContext("Unauthorized", 401);
response.setHeader("WWW-Authenticate", "Basic realm=\"WSO2-Registry\"");
return new ResponseTarget(context, response);
} else if ("Basic".equals(values[0])) {
try {
// Decode username/password
authorizationString = new String(Base64.decode(values[1]));
values = authorizationString.split("\\:");
String userName = values[0];
String password = values[1];
String tenantDomain =
(String) ((ServletRequestContext) request).getRequest().
getAttribute(MultitenantConstants.TENANT_DOMAIN);
int tenantId;
String userNameAlong;
if (tenantDomain == null) {
tenantId = getTenantId(userName);
userNameAlong = getUserName(userName);
} else {
tenantId = getTenantIdFromDomain(tenantDomain);
userNameAlong = userName;
}
registry = embeddedRegistryService.getRegistry(userNameAlong,
password, tenantId);
} catch (Exception e) {
final StringResponseContext response =
new StringResponseContext("Unauthorized", 401);
response.setHeader("WWW-Authenticate", "Basic realm=\"WSO2-Registry\"");
return new ResponseTarget(context, response);
}
} else {
// TODO - return an ExceptionTarget which contains the authentication problem
// return new ExceptionTarget(400, "Only basic authentication is supported!");
return null;
}
} else {
String tenantDomain = (String) requestContext.getRequest().
getAttribute(MultitenantConstants.TENANT_DOMAIN);
int calledTenantId = 0;
if (tenantDomain != null) {
if (RegistryContext.getBaseInstance().getRealmService() == null) {
String msg = "Error in getting the tenant manager. " +
"The realm service is not available.";
log.error(msg);
return new ResponseTarget(context, new EmptyResponseContext(400, msg));
}
TenantManager tenantManager =
RegistryContext.getBaseInstance().getRealmService().
getTenantManager();
try {
calledTenantId = tenantManager.getTenantId(tenantDomain);
} catch (org.wso2.carbon.user.api.UserStoreException e) {
String msg =
"Error in converting tenant domain to the id for tenant domain: " +
tenantDomain + ".";
log.error(msg, e);
return new ResponseTarget(context, new EmptyResponseContext(400, msg));
}
try {
if (!tenantManager.isTenantActive(calledTenantId)) {
// the tenant is not active.
String msg =
"The tenant is not active. tenant domain: " + tenantDomain +
".";
log.error(msg);
return new ResponseTarget(context, new EmptyResponseContext(400, msg));
}
} catch (org.wso2.carbon.user.api.UserStoreException e) {
String msg =
"Error in converting tenant domain to the id for tenant domain: " +
tenantDomain + ".";
log.error(msg, e);
return new ResponseTarget(context, new EmptyResponseContext(400, msg));
}
RegistryContext.getBaseInstance().
getRealmService().getBootstrapRealmConfiguration();
}
String anonUser = CarbonConstants.REGISTRY_ANONNYMOUS_USERNAME;
try {
registry = embeddedRegistryService.getRegistry(anonUser, calledTenantId);
} catch (RegistryException e) {
String msg = "Error in creating the registry.";
log.error(msg, e);
return new ResponseTarget(context, new EmptyResponseContext(400, msg));
}
}
}
// Squirrel this away so the adapter can get it later (after all that work we just did!)
context.setAttribute("userRegistry", registry);
final String method = context.getMethod();
/*
Following code moved further down
try {
uri = URLDecoder.decode(uri, "utf-8");
} catch (UnsupportedEncodingException e) {
log.error(e);
return null;
} */
if (uri.startsWith(RegistryConstants.PATH_SEPARATOR
+ RegistryConstants.REGISTRY_INSTANCE
+ RegistryConstants.PATH_SEPARATOR
+ RegistryConstants.REGISTRY_INSTANCE)) {
//if ROOT war is renamed to 'registry', uri will look like following,
//'/registry/registry/foo/bar'
//Hence,we need to remove the first 'registry'
uri = uri.replaceFirst(RegistryConstants.PATH_SEPARATOR
+ RegistryConstants.REGISTRY_INSTANCE, "");
}
// URI will start with the baseURI, which we need to strip off.
String[] excludeStartArr = {basePath + APPConstants.ATOM,
basePath + APPConstants.RESOURCE, basePath + "/tags"};
if (basePath == null) {
log.error("Base path is null. Aborting the operation.");
final StringResponseContext response =
new StringResponseContext("Internal Server Error", 500);
return new ResponseTarget(context, response);
} else if (!basePath.equals("")) {
for (String excludeStartStr : excludeStartArr) {
// URI will start with the baseURI, which we need to strip off.
if (uri.indexOf(excludeStartStr) > -1 &&
uri.length() > uri.indexOf(excludeStartStr) + basePath.length()) {
uri = uri.substring(uri.indexOf(excludeStartStr) + basePath.length());
break;
}
}
}
if (!uri.startsWith(
RegistryConstants.PATH_SEPARATOR + RegistryConstants.REGISTRY_INSTANCE)) {
uri = uri.substring(uri.indexOf(RegistryConstants.PATH_SEPARATOR));
}
context.setAttribute("pathInfo", uri);
String[] parts = splitPath(uri); // splits with "\;"
boolean hasColon = false;
TargetType type = null;
// Let's just see if this is an import first - in which case we can just send it
// on through.
if (parts.length > 1) {
String discriminator = parts[1];
// If this is a version request, don't do anything special. Otherwise process.
if (discriminator.startsWith("version:")) {
if (parts.length > 2) {
// Make sure this is a restore.
if (parts[2].equals("restore")) {
type = RESTORE_TYPE;
uri = parts[0] + RegistryConstants.URL_SEPARATOR + parts[1];
} else if (parts[2].equals(APPConstants.ASSOCIATIONS)) {
type = ASSOCIATIONS_TYPE;
uri = parts[0] + RegistryConstants.URL_SEPARATOR + parts[1];
} else {
// There's an extra semicolon here somewhere.
return null;
}
}
} else {
// Store the split URL for later
context.setAttribute("splitPath", parts);
int idx = discriminator.indexOf("?");
if (idx > -1) {
discriminator = discriminator.substring(0, idx);
}
String suffix = null;
idx = discriminator.indexOf(":");
if (idx > -1) {
suffix = discriminator.substring(idx + 1, discriminator.length());
discriminator = discriminator.substring(0, idx);
hasColon = true;
}
if (discriminator.startsWith("aspect")) {
type = ASPECT_TYPE;
} else {
type = types.get(discriminator);
}
if (discriminator.equals("tag") && method.equals("DELETE") && hasColon) {
context.setAttribute("tagName", suffix);
type = DELETE_TYPE;
} else if (discriminator.equals("comment") && method.equals("DELETE") && hasColon) {
context.setAttribute("commentId", suffix);
type = DELETE_TYPE;
}
// If we have a discriminator that we don't understand, return a 404
if (type == null) {
return null;
}
// For the rest of this code, we'll want the "raw" resource URI
if (!hasColon || !(type.equals(COMMENTS_TYPE) || type.equals(RATINGS_TYPE) ||
type.equals(TAGS_TYPE))) {
uri = parts[0];
}
if (hasColon && (type.equals(RATINGS_TYPE) || type.equals(TAGS_TYPE))) {
type = null;
}
}
}
int idx = uri.indexOf("?");
if (idx > -1) {
String queryString = uri.substring(idx + 1, uri.length());
context.setAttribute("queryString", queryString);
uri = uri.substring(0, idx);
}
try {
uri = URLDecoder.decode(uri, "utf-8");
} catch (UnsupportedEncodingException e) {
log.error(e);
return null;
}
boolean isMedia = false;
if (uri.startsWith(APPConstants.RESOURCE)) {
uri = uri.substring(APPConstants.RESOURCE.length());
isMedia = true;
} else if (uri.startsWith(APPConstants.ATOM)) {
uri = uri.substring(APPConstants.ATOM.length());
} else if (uri.startsWith("/tags") && (uri.length() == 5 || uri.charAt(5) == '/')) {
return new SimpleTarget(TAG_URL_TYPE, context);
} else {
return null;
}
if (uri.length() == 0) {
uri = "/";
}
// See if we're asking for a paginated collection
String startParam = context.getParameter("start");
String pageLenParam = context.getParameter("pageLen");
int start = (startParam == null) ? -1 : Integer.parseInt(startParam);
int pageLen = (pageLenParam == null) ? -1 : Integer.parseInt(pageLenParam);
Resource resource = null;
if (type != null && type.equals(DUMP_TYPE) &&
method != null && method.equals("POST")) {
// for restoring a dump we don't need to have available resource
// here we will create a fake resource to store the path
resource = new ResourceImpl();
((ResourceImpl) resource).setPath(uri);
} else {
// in a restore, path don't need to exist.
try {
CurrentSession.setUserRealm(registry.getUserRealm());
CurrentSession.setUser(registry.getUserName());
if (!AuthorizationUtils.authorize(RegistryUtils.getAbsolutePath(
registry.getRegistryContext(), uri),
ActionConstants.GET)) {
final StringResponseContext response =
new StringResponseContext("Unauthorized", 401);
response.setHeader("WWW-Authenticate", "Basic realm=\"WSO2-Registry\"");
return new ResponseTarget(context, response);
} else if (start > -1 || pageLen > -1) {
resource = registry.get(uri, start, pageLen);
} else {
resource = registry.get(uri);
}
} catch (AuthorizationFailedException e) {
final StringResponseContext response =
new StringResponseContext("Unauthorized", 401);
response.setHeader("WWW-Authenticate", "Basic realm=\"WSO2-Registry\"");
return new ResponseTarget(context, response);
} catch (ResourceNotFoundException e) {
// If this is a straight-ahead POST to a non-existent directory, create it?
if (method.equals("POST") && parts.length == 1) {
// Need to create it.
try {
Collection c = registry.newCollection();
registry.put(uri, c);
resource = registry.get(uri);
} catch (RegistryException e1) {
log.error(e1);
return null;
}
}
if (resource == null) {
return null;
}
} catch (RegistryException e) {
return null; // return 404
}
if (method.equals("GET")) {
// eTag based conditional get
String ifNonMatchValue = context.getHeader("if-none-match");
if (ifNonMatchValue != null) {
String currentETag = Utils.calculateEntityTag(resource);
if (ifNonMatchValue.equals(currentETag)) {
/* the version is not modified */
ResponseContext response = new StringResponseContext("Not Modified", 304);
return new ResponseTarget(context, response);
}
}
// date based conditional get
long ifModifiedSinceValue = 0;
Date ifModifiedSince = context.getDateHeader("If-Modified-Since");
if (ifModifiedSince != null) {
ifModifiedSinceValue = ifModifiedSince.getTime();
}
if (ifModifiedSinceValue > 0) {
long lastModifiedValue = resource.getLastModified().getTime();
// convert the time values from milliseconds to seconds
ifModifiedSinceValue /= 1000;
lastModifiedValue /= 1000;
/* condition to check we have latest updates in terms of dates */
if (ifModifiedSinceValue >= lastModifiedValue) {
/* no need to response with data */
ResponseContext response = new StringResponseContext("Not Modified", 304);
return new ResponseTarget(context, response);
}
}
}
}
context.setAttribute("MyResolver", this);
if (type == null) {
if (method.equals("DELETE")) {
// Unfortunately, deletions aren't quite handled the way we want them
// in AbstractEntityCollectionProvider, so for now we're using an
// extensionRequest to get it done.