use of org.forgerock.json.resource.Request in project OpenAM by OpenRock.
the class RestSTSInstancePublisherImpl method publishInstance.
/**
* Publishes the rest STS instance at the specified relative path. This method will be invoked when the Rest STS instance
* is initially published, and to re-constitute previously-published instances following a server restart.
* Note on transaction semantics: publishing a rest-sts instance means modifying both the CREST router, and the SMS.
* First the CREST router is modified, and then the SMS. If the SMS modifications fail, the CREST router modifications
* will be rolled-back, so that a publish can be successfully re-tried.
* @param instanceConfig The RestSTSInstanceConfig which defined the guice bindings which specify the functionality of
* the RestSTS instance. This RestSTSInstanceConfig will be persisted so that persisted instances
* can be reconstituted in case of a server restart.
* @param restSTSInstance The RestSTS instance defining the functionality of the rest STS service.
* @param republish Indicates whether this is an original publish, or a republish following OpenAM restart.
* @throws STSPublishException thrown in case a rest-sts instance has already been published at the specified
* subPath, or in case other errors prevented a successful publish.
*/
@Override
public synchronized String publishInstance(RestSTSInstanceConfig instanceConfig, RestSTS restSTSInstance, boolean republish) throws STSPublishException {
/*
Exclude the possibility that a rest-sts instance has already been added at the sub-path.
Looking at the router.add code to determine what happens if route already exists: it looks like it amounts to a no-op -
the backing route collection is a CopyOnWriteArraySet, which will just return false if the add did not work, but
because this value is not returned, we don't know what the outcome of the operation was. But because the Route class
is contained in the CoWAS, and it does not over-ride the equals method, every new reference to a Route will be added -
i.e. equality is defined as reference equality. So it seems possible to add the same path several times, and the
specific SingletonResourceProvider chosen to service a given request is a function of the RouteMatcher.
But because it should not be possible to add a new rest-sts instance at the same path, I can avoid all of these
complexities by checking my HashMap if an entry is present, as I need to maintain a reference to all
published Routes in order to be able to remove them.
*/
String deploymentSubPath = deploymentPathNormalization.normalizeDeploymentPath(instanceConfig.getDeploymentSubPath());
if (publishedRoutes.containsKey(normalizeDeploymentSubPathForRouteCache(deploymentSubPath))) {
throw new STSPublishException(ResourceException.CONFLICT, "A rest-sts instance at sub-path " + deploymentSubPath + " has already been published.");
}
// Use InjectorHolder to lookup AuditFilter as Guice struggles to inject it
AuditFilter auditFilter = InjectorHolder.getInstance(AuditFilter.class);
FilterChain auditedRestSTSService = new FilterChain(Resources.newSingleton(new RestSTSService(restSTSInstance, logger)), new AuditFilterWrapper(auditFilter, STS));
RouteMatcher<Request> route = router.addRoute(EQUALS, uriTemplate(deploymentSubPath), auditedRestSTSService);
/*
Need to persist the published Route instance as it is necessary for router removal.
*/
publishedRoutes.put(normalizeDeploymentSubPathForRouteCache(deploymentSubPath), route);
/*
If this is a republish (i.e. re-constitute previously-published Rest STS instances following OpenAM restart),
then the RestSTSInsanceConfig does not need to be persisted, as it was obtained from the SMS via a GET
on the publish service by the RestSTSInstanceRepublishServlet.
*/
if (!republish) {
try {
persistentStore.persistSTSInstance(deploymentSubPath, instanceConfig.getDeploymentConfig().getRealm(), instanceConfig);
} catch (STSPublishException e) {
//roll-back the router mutation before throwing exception
router.removeRoute(route);
publishedRoutes.remove(normalizeDeploymentSubPathForRouteCache(deploymentSubPath));
throw e;
}
}
return deploymentSubPath;
}
use of org.forgerock.json.resource.Request in project OpenAM by OpenRock.
the class SmsRequestHandler method addService.
/**
* Adds routes for the specified service to the provided router. Realm schema routes are added if the
* {@link #schemaType} is either {@link SchemaType#GLOBAL} (for default values) or
* {@link SchemaType#ORGANIZATION}. Global schema routes are only added for {@link SchemaType#GLOBAL}.
*
* @param sm The ServiceManager instance to use.
* @param serviceName The name of the service being added.
* @param serviceVersion The version of the service being added.
* @return The routes that were configured.
* @throws SMSException From downstream service manager layer.
* @throws SSOException From downstream service manager layer.
*/
private Map<SmsRouteTree, Set<RouteMatcher<Request>>> addService(ServiceManager sm, String serviceName, String serviceVersion) throws SMSException, SSOException {
if (excludedServices.contains(serviceName)) {
debug.message("Excluding service from REST SMS: {}", serviceName);
return null;
}
ServiceSchemaManager ssm = sm.getSchemaManager(serviceName, serviceVersion);
String resourceName = EMPTY_PATH.equals(ssm.getResourceName()) ? "" : ssm.getResourceName();
Map<SmsRouteTree, Set<RouteMatcher<Request>>> routes = new HashMap<>();
ServiceSchema organizationSchema = ssm.getOrganizationSchema();
ServiceSchema dynamicSchema = ssm.getDynamicSchema();
if (schemaType == SchemaType.GLOBAL) {
ServiceSchema globalSchema = ssm.getGlobalSchema();
if (hasGlobalSchema(globalSchema)) {
debug.message("Adding global schema REST SMS endpoints for service: {}", serviceName);
addGlobalPaths(resourceName, new ArrayList<ServiceSchema>(), globalSchema, organizationSchema, dynamicSchema, routes, DEFAULT_IGNORED_ROUTES, null);
} else if (organizationSchema != null) {
debug.message("Adding global schema REST SMS endpoints for service: {}", serviceName);
addGlobalPaths(resourceName, new ArrayList<ServiceSchema>(), organizationSchema, organizationSchema, dynamicSchema, routes, DEFAULT_IGNORED_ROUTES, null);
}
} else {
if (organizationSchema != null) {
debug.message("Adding realm schema REST SMS endpoints for service: {}", serviceName);
addPaths(resourceName, new ArrayList<ServiceSchema>(), organizationSchema, dynamicSchema, routes, DEFAULT_IGNORED_ROUTES, null);
} else if (dynamicSchema != null) {
debug.message("Adding realm schema REST SMS endpoints for service: {}", serviceName);
addPaths(resourceName, new ArrayList<ServiceSchema>(), dynamicSchema, dynamicSchema, routes, DEFAULT_IGNORED_ROUTES, null);
}
}
return routes;
}
use of org.forgerock.json.resource.Request in project OpenAM by OpenRock.
the class SmsRequestHandler method createServices.
/**
* Creates a {@link Router} for all the registered services, and then assigns that router to the instance so that
* it will be used for all future requests.
* @throws SMSException From downstream service manager layer.
* @throws SSOException From downstream service manager layer.
*/
private synchronized void createServices() throws SSOException, SMSException {
Map<String, Map<SmsRouteTree, Set<RouteMatcher<Request>>>> serviceRoutes = new HashMap<>();
ServiceManager sm = getServiceManager();
Set<String> serviceNames = sm.getServiceNames();
for (String serviceName : serviceNames) {
Map<SmsRouteTree, Set<RouteMatcher<Request>>> routes = addService(sm, serviceName, DEFAULT_VERSION);
if (routes != null) {
serviceRoutes.put(serviceName, routes);
}
}
if (schemaType == SchemaType.GLOBAL) {
addServersRoutes(sm, serviceRoutes);
}
this.serviceRoutes = serviceRoutes;
}
use of org.forgerock.json.resource.Request in project OpenAM by OpenRock.
the class SmsRequestHandler method addServersRoutes.
private void addServersRoutes(ServiceSchemaManager ssm, Set<RouteMatcher<Request>> serviceRoutes, String parentName, String schemaName) throws SSOException, SMSException {
ServiceSchema parentSchema = ssm.getGlobalSchema().getSubSchema(parentName);
ServiceSchema schema = parentSchema.getSubSchema(schemaName);
HashMap<SmsRouteTree, Set<RouteMatcher<Request>>> routes = new HashMap<>();
addPaths("", new ArrayList<>(Collections.singletonList(parentSchema)), schema, null, routes, Collections.<Pattern>emptyList(), routeTree);
serviceRoutes.addAll(routes.get(routeTree));
}
use of org.forgerock.json.resource.Request in project OpenAM by OpenRock.
the class SmsRequestHandler method addRoute.
private Map<SmsRouteTree, Set<RouteMatcher<Request>>> addRoute(ServiceSchema schema, RoutingMode mode, String path, RequestHandler handler, List<Pattern> ignoredRoutes, SmsRouteTree routeTree) {
for (Pattern ignored : ignoredRoutes) {
if (ignored.matcher(path).matches()) {
return emptyMap();
}
}
SmsRouteTree tree = routeTree == null ? this.routeTree.handles(schema.getServiceName()) : routeTree;
RouteMatcher<Request> route = tree.addRoute(mode, path, handler);
return Maps.newHashMap(Collections.singletonMap(tree, asSet(route)));
}
Aggregations