/** * Persist the supplied {@link JsonValue} {@code value} as the new state of this singleton * relationship on {@code resourceId}. * * <p><em>This is currently the only means of creating an instance of this singleton</em> * * @param context The context of this request * @param resourceId Id of the resource relation fields in value are to be memebers of * @param value A {@link JsonValue} map of relationship fields and their values * @return The persisted instance of {@code value} */ @Override public Promise<JsonValue, ResourceException> setRelationshipValueForResource( Context context, String resourceId, JsonValue value) { if (value.isNotNull()) { try { final JsonValue id = value.get(FIELD_ID); // Update if we got an id, otherwise replace if (id != null && id.isNotNull()) { final UpdateRequest updateRequest = Requests.newUpdateRequest("", value); updateRequest.setAdditionalParameter(PARAM_FIRST_ID, resourceId); return updateInstance(context, value.get(FIELD_ID).asString(), updateRequest) .then( new Function<ResourceResponse, JsonValue, ResourceException>() { @Override public JsonValue apply(ResourceResponse resourceResponse) throws ResourceException { return resourceResponse.getContent(); } }); } else { // no id, replace current instance clear(context, resourceId); final CreateRequest createRequest = Requests.newCreateRequest("", value); createRequest.setAdditionalParameter(PARAM_FIRST_ID, resourceId); return createInstance(context, createRequest) .then( new Function<ResourceResponse, JsonValue, ResourceException>() { @Override public JsonValue apply(ResourceResponse resourceResponse) throws ResourceException { return resourceResponse.getContent(); } }); } } catch (ResourceException e) { return e.asPromise(); } } else { clear(context, resourceId); return newResultPromise(json(null)); } }
/** * Update a link. * * @throws SynchronizationException if updating link fails */ void update() throws SynchronizationException { if (_id == null) { throw new SynchronizationException("Attempt to update non-existent link"); } JsonValue jv = toJsonValue(); try { UpdateRequest r = Requests.newUpdateRequest(linkId(_id), jv); r.setRevision(_rev); Resource resource = mapping .getService() .getConnectionFactory() .getConnection() .update(mapping.getService().getServerContext(), r); _rev = resource.getRevision(); } catch (ResourceException ose) { LOGGER.warn("Failed to update link", ose); throw new SynchronizationException(ose); } }
/** {@inheritDoc} */ @Override public void updateInstance( final ServerContext context, final String resourceId, final UpdateRequest request, final ResultHandler<Resource> handler) { RealmContext realmContext = context.asContext(RealmContext.class); String realmPath = realmContext.getResolvedRealm(); final JsonValue realmDetails = request.getContent(); Resource resource; String realm = null; OrganizationConfigManager ocm; OrganizationConfigManager realmCreatedOcm; String principalName = PrincipalRestUtils.getPrincipalNameFromServerContext(context); try { hasPermission(context); realm = checkForTopLevelRealm(resourceId); if (realm != null && !realm.startsWith("/")) { realm = "/" + realm; } if (!realmPath.equalsIgnoreCase("/")) { realm = realmPath + realm; } // The initial attempt to UPDATE a realm, // if the realm does not exist it must be created ocm = new OrganizationConfigManager(getSSOToken(), realm); List newServiceNames; // update ID_REPO attributes updateConfiguredServices(ocm, createServicesMap(realmDetails)); newServiceNames = realmDetails.get(SERVICE_NAMES).asList(); if (newServiceNames == null || newServiceNames.isEmpty()) { debug.error("RealmResource.updateInstance() : No Services defined."); } else { assignServices(ocm, newServiceNames); // assign services to realm } // READ THE REALM realmCreatedOcm = new OrganizationConfigManager(getSSOToken(), realm); debug.message( "RealmResource.updateInstance :: UPDATE of realm " + realm + " performed by " + principalName); // create a resource for handler to return resource = new Resource( realm, String.valueOf(System.currentTimeMillis()), createJsonMessage("realmUpdated", realmCreatedOcm.getOrganizationName())); handler.handleResult(resource); } catch (SMSException e) { try { configureErrorMessage(e); } catch (NotFoundException nfe) { if (debug.errorEnabled()) { debug.error( "RealmResource.updateInstance()" + "Cannot find " + resourceId + ":" + e + "\n" + "CREATING " + resourceId); } // Realm was NOT found, therefore create the realm try { String parentRealm = RealmUtils.getParentRealm(realm); String childRealm = RealmUtils.getChildRealm(realm); ocm = new OrganizationConfigManager(getSSOToken(), parentRealm); // create the realm createOrganization(ocm, realmDetails, childRealm, realmPath); // read the realm to make sure that it has been created... realmCreatedOcm = new OrganizationConfigManager(getSSOToken(), realm); if (debug.messageEnabled()) { debug.message( "RealmResource.updateInstance :: UPDATE of realm " + realm + " performed by " + principalName); } resource = new Resource( childRealm, String.valueOf(System.currentTimeMillis()), createJsonMessage("realmCreated", realmCreatedOcm.getOrganizationName())); if (debug.messageEnabled()) { debug.message("RealmResource :: UPDATE : Updated resource with ID, " + resourceId); } handler.handleResult(resource); } catch (SMSException smse) { debug.error("RealmResource.updateInstance() : Cannot UPDATE " + resourceId, smse); try { configureErrorMessage(smse); } catch (NotFoundException nf) { debug.error("RealmResource.updateInstance() : Cannot find " + resourceId, nf); handler.handleError(nf); } catch (ForbiddenException fe) { // User does not have authorization debug.error("RealmResource.updateInstance() : Cannot UPDATE " + resourceId, fe); handler.handleError(fe); } catch (PermanentException pe) { debug.error("RealmResource.updateInstance() Cannot UPDATE " + resourceId, pe); // Cannot recover from this exception handler.handleError(pe); } catch (ConflictException ce) { debug.error("RealmResource.updateInstance() : Cannot UPDATE " + resourceId, ce); handler.handleError(ce); } catch (BadRequestException be) { debug.error("RealmResource.updateInstance() : Cannot UPDATE " + resourceId, be); handler.handleError(be); } } catch (Exception ex) { debug.error("RealmResource.updateInstance() : Cannot UPDATE " + resourceId, ex); handler.handleError(new NotFoundException("Cannot update realm.", ex)); } } catch (ForbiddenException fe) { // User does not have authorization debug.error("RealmResource.updateInstance() : Cannot UPDATE " + resourceId, fe); handler.handleError(fe); } catch (PermanentException pe) { debug.error("RealmResource.updateInstance() : Cannot UPDATE " + resourceId, pe); // Cannot recover from this exception handler.handleError(pe); } catch (ConflictException ce) { debug.error("RealmResource.updateInstance() : Cannot UPDATE " + resourceId, ce); handler.handleError(ce); } catch (BadRequestException be) { debug.error("RealmResource.updateInstance() : Cannot UPDATE " + resourceId, be); handler.handleError(be); } catch (Exception ex) { debug.error("RealmResource.updateInstance() : Cannot UPDATE " + resourceId, ex); handler.handleError(new NotFoundException("Cannot update realm.", ex)); } } catch (SSOException sso) { debug.error("RealmResource.updateInstance() : Cannot UPDATE " + resourceId, sso); handler.handleError(new PermanentException(401, "Access Denied", null)); } catch (ForbiddenException fe) { debug.error("RealmResource.updateInstance() : Cannot UPDATE " + resourceId, fe); handler.handleError(fe); } catch (PermanentException pe) { debug.error("RealmResource.Instance() : Cannot UPDATE " + resourceId, pe); // Cannot recover from this exception handler.handleError(pe); } catch (Exception ex) { debug.error("RealmResource.updateInstance() : Cannot UPDATE " + resourceId, ex); handler.handleError(new NotFoundException("Cannot update realm.", ex)); } }
/** * Updates the specified object in the object set. * * <p>This implementation does not require MVCC and uses the current revision if no revision is * specified in the request. * * <p>If successful, this method updates metadata properties within the passed object, including: * a new {@code _rev} value for the revised object's version * * @param request the contents of the object to update * @throws ConflictException if version is required but is {@code null}. * @throws ForbiddenException if access to the object is forbidden. * @throws NotFoundException if the specified object could not be found. * @throws PreconditionFailedException if version did not match the existing object in the set. * @throws BadRequestException if the passed identifier is invalid */ @Override public ResourceResponse update(UpdateRequest request) throws ResourceException { if (request.getResourcePathObject().size() < 2) { throw new NotFoundException( "The object identifier did not include sufficient information to determine the object type and identifier of the object to update: " + request.getResourcePath()); } final String type = request.getResourcePathObject().parent().toString(); final String localId = request.getResourcePathObject().leaf(); String orientClassName = typeToOrientClassName(type); JsonValue obj = request.getContent(); if (request.getRevision() != null && !"".equals(request.getRevision())) { obj.put(DocumentUtil.TAG_REV, request.getRevision()); } ODatabaseDocumentTx db = getConnection(); try { ODocument existingDoc = predefinedQueries.getByID(localId, type, db); if (existingDoc == null) { throw new NotFoundException( "Update on object " + request.getResourcePath() + " could not find existing object."); } ODocument updatedDoc = DocumentUtil.toDocument(obj, existingDoc, db, orientClassName); logger.trace("Updated doc for id {} to save {}", request.getResourcePath(), updatedDoc); updatedDoc.save(); obj.put(DocumentUtil.TAG_REV, Integer.toString(updatedDoc.getVersion())); // Set ID to return to caller obj.put(DocumentUtil.TAG_ID, updatedDoc.field(DocumentUtil.ORIENTDB_PRIMARY_KEY)); logger.debug( "Committed update for id: {} revision: {}", request.getResourcePath(), updatedDoc.getVersion()); logger.trace("Update payload for id: {} doc: {}", request.getResourcePath(), updatedDoc); return newResourceResponse( obj.get(DocumentUtil.TAG_ID).asString(), obj.get(DocumentUtil.TAG_REV).asString(), obj); } catch (ODatabaseException ex) { // Without transaction the concurrent modification exception gets nested instead if (isCauseConcurrentModificationException(ex, 10)) { throw new PreconditionFailedException( "Update rejected as current Object revision is different than expected by caller, the object has changed since retrieval: " + ex.getMessage(), ex); } else { throw ex; } } catch (OConcurrentModificationException ex) { throw new PreconditionFailedException( "Update rejected as current Object revision is different than expected by caller, the object has changed since retrieval: " + ex.getMessage(), ex); } catch (RuntimeException e) { throw e; } finally { if (db != null) { db.close(); } } }
void doPut(final HttpServletRequest req, final HttpServletResponse resp) { try { // Parse out the required API versions. final AcceptAPIVersion acceptVersion = parseAcceptAPIVersion(req); // Prepare response. prepareResponse(req, resp); // Validate request. preprocessRequest(req); if (req.getHeader(HEADER_IF_MATCH) != null && req.getHeader(HEADER_IF_NONE_MATCH) != null) { // FIXME: i18n throw new PreconditionFailedException( "Simultaneous use of If-Match and If-None-Match not " + "supported for PUT requests"); } final Map<String, String[]> parameters = req.getParameterMap(); final JsonValue content = getJsonContent(req); final String rev = getIfNoneMatch(req); if (ETAG_ANY.equals(rev)) { // This is a create with a user provided resource ID: split the // path into the parent resource name and resource ID. final String resourceName = getResourceName(req); final int i = resourceName.lastIndexOf('/'); final CreateRequest request; if (resourceName.isEmpty()) { // FIXME: i18n. throw new BadRequestException("No new resource ID in HTTP PUT request"); } else if (i < 0) { // We have a pathInfo of the form "{id}" request = Requests.newCreateRequest(EMPTY_STRING, content); request.setNewResourceId(resourceName); } else { // We have a pathInfo of the form "{container}/{id}" request = Requests.newCreateRequest(resourceName.substring(0, i), content); request.setNewResourceId(resourceName.substring(i + 1)); } for (final Map.Entry<String, String[]> p : parameters.entrySet()) { final String name = p.getKey(); final String[] values = p.getValue(); if (HttpUtils.isMultiPartRequest(req.getContentType())) { // Ignore - multipart content adds form parts to the parameter set } else if (parseCommonParameter(name, values, request)) { continue; } else { request.setAdditionalParameter(name, asSingleValue(name, values)); } } doRequest(req, resp, acceptVersion, request); } else { final UpdateRequest request = Requests.newUpdateRequest(getResourceName(req), content).setRevision(getIfMatch(req)); for (final Map.Entry<String, String[]> p : parameters.entrySet()) { final String name = p.getKey(); final String[] values = p.getValue(); if (HttpUtils.isMultiPartRequest(req.getContentType())) { // Ignore - multipart content adds form parts to the parameter set } else if (parseCommonParameter(name, values, request)) { continue; } else { request.setAdditionalParameter(name, asSingleValue(name, values)); } } doRequest(req, resp, acceptVersion, request); } } catch (final Exception e) { fail(req, resp, e); } }
/** * Stores the <code>Dictionary</code> under the given <code>pid</code>. * * @param pid The identifier of the dictionary. * @param properties The <code>Dictionary</code> to store. * @throws IOException If an error occurrs storing the dictionary. If this exception is thrown, it * is expected, that {@link #exists(String) exists(pid} returns <code>false</code>. */ public void store(String pid, Dictionary properties) throws IOException { logger.debug("Store call for {} {}", pid, properties); // Store config handling settings in memory if (pid.startsWith("org.apache.felix.fileinstall")) { tempStore.put(pid, properties); return; } try { if (isReady(0) && requireRepository) { String id = pidToId(pid); Map<String, Object> obj = dictToMap(properties); JsonValue content = new JsonValue(obj); String configResourceId = ConfigBootstrapHelper.getId( content.get(ConfigBootstrapHelper.CONFIG_ALIAS).asString(), content.get(ConfigBootstrapHelper.SERVICE_PID).asString(), content.get(ConfigBootstrapHelper.SERVICE_FACTORY_PID).asString()); String configString = (String) obj.get(JSONEnhancedConfig.JSON_CONFIG_PROPERTY); Map<Object, Object> configMap = deserializeConfig(configString); if (configMap != null) { configMap.put("_id", configResourceId); } obj.put(JSONEnhancedConfig.JSON_CONFIG_PROPERTY, configMap); Map<String, Object> existing = null; try { ReadRequest readRequest = Requests.newReadRequest(id); existing = repo.read(readRequest).getContent().asMap(); } catch (NotFoundException ex) { // Just detect that it doesn't exist } if (existing != null) { String rev = (String) existing.get("_rev"); existing.remove("_rev"); existing.remove("_id"); obj.remove("_rev"); // beware, this means _id and _rev should not be in config file obj.remove("_id"); // beware, this means _id and _rev should not be in config file obj.remove(RepoPersistenceManager.BUNDLE_LOCATION); obj.remove(RepoPersistenceManager.FELIX_FILEINSTALL_FILENAME); if (!existing.equals(obj)) { logger.trace("Not matching {} {}", existing, obj); boolean retry; do { retry = false; try { UpdateRequest r = Requests.newUpdateRequest(id, new JsonValue(obj)); r.setRevision(rev); repo.update(r); } catch (PreconditionFailedException ex) { logger.debug("Concurrent change during update, retrying {} {}", pid, rev); ReadRequest readRequest = Requests.newReadRequest(id); existing = repo.read(readRequest).getContent().asMap(); retry = true; } } while (retry); logger.debug("Updated existing config {} {} {}", new Object[] {pid, rev, obj}); } else { logger.debug( "Existing config same as store request, ignoring {} {} {}", new Object[] {pid, rev, obj}); } } else { logger.trace("Creating: {} {} ", id, obj); // This may create a new (empty) configuration, which felix marks with // _felix___cm__newConfiguration=true String newResourceId = id.substring(CONFIG_CONTEXT_PREFIX.length()); CreateRequest createRequest = Requests.newCreateRequest(CONFIG_CONTEXT_PREFIX, new JsonValue(obj)); createRequest.setNewResourceId(newResourceId); obj = repo.create(createRequest).getContent().asMap(); logger.debug("Stored new config in repository {} {}", pid, obj); } } else { tempStore.put(pid, properties); logger.debug("Stored in memory {} {}", pid, properties); } } catch (ResourceException ex) { throw new IOException("Failed to store configuration in repository: " + ex.getMessage(), ex); } }