@@ -95,9 +95,7 @@ String body() {
9595 private enum Error {
9696 ALREADY_EXISTS (409 , "global" , "alreadyExists" , "ALREADY_EXISTS" ),
9797 PERMISSION_DENIED (403 , "global" , "forbidden" , "PERMISSION_DENIED" ),
98- // change failed precondition error code to 412 when #440 is fixed
9998 FAILED_PRECONDITION (400 , "global" , "failedPrecondition" , "FAILED_PRECONDITION" ),
100- // change invalid argument error code to 412 when #440 is fixed
10199 INVALID_ARGUMENT (400 , "global" , "badRequest" , "INVALID_ARGUMENT" ),
102100 BAD_REQUEST (400 , "global" , "badRequest" , "BAD_REQUEST" ),
103101 INTERNAL_ERROR (500 , "global" , "internalError" , "INTERNAL_ERROR" );
@@ -324,12 +322,9 @@ Response create(Project project) {
324322 }
325323 }
326324
327- Response delete (String projectId ) {
325+ synchronized Response delete (String projectId ) {
328326 Project project = projects .get (projectId );
329327 if (project == null ) {
330- // Currently the service returns 403 Permission Denied when trying to delete a project that
331- // doesn't exist. Here we mimic this behavior, but this line should be changed to throw a
332- // 404 Not Found error when the service fixes this (#440).
333328 return Error .PERMISSION_DENIED .response (
334329 "Error when deleting " + projectId + " because the project was not found." );
335330 }
@@ -343,18 +338,16 @@ Response delete(String projectId) {
343338 }
344339
345340 Response get (String projectId , String [] fields ) {
346- if (!projects .containsKey (projectId )) {
347- // Currently the service returns 403 Permission Denied when trying to get a project that
348- // doesn't exist. Here we mimic this behavior, but this line should be changed to throw a
349- // 404 Not Found error when the service fixes this (#440).
350- return Error .PERMISSION_DENIED .response ("Project " + projectId + " not found." );
351- }
352341 Project project = projects .get (projectId );
353- try {
354- return new Response (HTTP_OK , jsonFactory .toString (extractFields (project , fields )));
355- } catch (IOException e ) {
356- return Error .INTERNAL_ERROR .response (
357- "Error when serializing project " + project .getProjectId ());
342+ if (project != null ) {
343+ try {
344+ return new Response (HTTP_OK , jsonFactory .toString (extractFields (project , fields )));
345+ } catch (IOException e ) {
346+ return Error .INTERNAL_ERROR .response (
347+ "Error when serializing project " + project .getProjectId ());
348+ }
349+ } else {
350+ return Error .PERMISSION_DENIED .response ("Project " + projectId + " not found." );
358351 }
359352 }
360353
@@ -462,12 +455,9 @@ private static Project extractFields(Project fullProject, String[] fields) {
462455 return project ;
463456 }
464457
465- Response replace (String projectId , Project project ) {
458+ synchronized Response replace (String projectId , Project project ) {
466459 Project originalProject = projects .get (projectId );
467460 if (originalProject == null ) {
468- // Currently the service returns 403 Permission Denied when trying to replace a project that
469- // doesn't exist. Here we mimic this behavior, but this line should be changed to throw a
470- // 404 Not Found error when the service fixes this (#440).
471461 return Error .PERMISSION_DENIED .response (
472462 "Error when replacing " + projectId + " because the project was not found." );
473463 } else if (!originalProject .getLifecycleState ().equals ("ACTIVE" )) {
@@ -478,23 +468,23 @@ Response replace(String projectId, Project project) {
478468 "The server currently only supports setting the parent once "
479469 + "and does not allow unsetting it." );
480470 }
481- originalProject .setName (project .getName ());
482- originalProject .setLabels (project .getLabels ());
483- originalProject .setParent (project .getParent ());
471+ project .setProjectId (projectId );
472+ project .setLifecycleState (originalProject .getLifecycleState ());
473+ project .setCreateTime (originalProject .getCreateTime ());
474+ project .setProjectNumber (originalProject .getProjectNumber ());
475+ // replace cannot fail because both this method and removeProject are synchronized
476+ projects .replace (projectId , project );
484477 try {
485- return new Response (HTTP_OK , jsonFactory .toString (originalProject ));
478+ return new Response (HTTP_OK , jsonFactory .toString (project ));
486479 } catch (IOException e ) {
487480 return Error .INTERNAL_ERROR .response ("Error when serializing project " + projectId );
488481 }
489482 }
490483
491- Response undelete (String projectId ) {
484+ synchronized Response undelete (String projectId ) {
492485 Project project = projects .get (projectId );
493486 Response response ;
494487 if (project == null ) {
495- // Currently the service returns 403 Permission Denied when trying to undelete a project that
496- // doesn't exist. Here we mimic this behavior, but this line should be changed to throw a
497- // 404 Not Found error when the service fixes this (#440).
498488 response = Error .PERMISSION_DENIED .response (
499489 "Error when undeleting " + projectId + " because the project was not found." );
500490 } else if (!project .getLifecycleState ().equals ("DELETE_REQUESTED" )) {
@@ -550,7 +540,7 @@ public void stop() {
550540 *
551541 * @return true if the lifecycle state was successfully updated, false otherwise.
552542 */
553- public boolean changeLifecycleState (String projectId , String lifecycleState ) {
543+ public synchronized boolean changeLifecycleState (String projectId , String lifecycleState ) {
554544 checkArgument (
555545 "ACTIVE" .equals (lifecycleState ) || "DELETE_REQUESTED" .equals (lifecycleState )
556546 || "DELETE_IN_PROGRESS" .equals (lifecycleState ),
@@ -571,7 +561,9 @@ public boolean changeLifecycleState(String projectId, String lifecycleState) {
571561 *
572562 * @return true if the project was successfully deleted, false if the project didn't exist.
573563 */
574- public boolean removeProject (String projectId ) {
564+ public synchronized boolean removeProject (String projectId ) {
565+ // Because this method is synchronized, any code that relies on non-atomic read/write operations
566+ // should not fail if that code is also synchronized.
575567 return projects .remove (checkNotNull (projectId )) != null ;
576568 }
577569}
0 commit comments