// Path: coopr-server/src/main/java/co/cask/coopr/account/Account.java
// public final class Account {
//   public static final Account SUPERADMIN = new Account(Constants.ADMIN_USER, Constants.SUPERADMIN_TENANT);
//   private final String userId;
//   private final String tenantId;
// 
//   public Account(String userId, String tenantId) {
//     Preconditions.checkArgument(userId != null && !userId.isEmpty(), "Account must have a user id.");
//     Preconditions.checkArgument(tenantId != null && !tenantId.isEmpty(), "Account must have a tenant id.");
//     this.userId = userId;
//     this.tenantId = tenantId;
//   }
// 
//   public String getUserId() {
//     return userId;
//   }
// 
//   public String getTenantId() {
//     return tenantId;
//   }
// 
//   public boolean isAdmin() {
//     return Constants.ADMIN_USER.equals(userId);
//   }
// 
//   public boolean isSuperadmin() {
//     return Constants.ADMIN_USER.equals(userId) && Constants.SUPERADMIN_TENANT.equals(tenantId);
//   }
// 
//   @Override
//   public boolean equals(Object o) {
//     if (this == o) {
//       return true;
//     }
//     if (!(o instanceof Account)) {
//       return false;
//     }
// 
//     Account other = (Account) o;
//     return Objects.equal(userId, other.userId) &&
//       Objects.equal(tenantId, other.tenantId);
//   }
// 
//   @Override
//   public int hashCode() {
//     return Objects.hashCode(userId, tenantId);
//   }
// 
//   @Override
//   public String toString() {
//     return Objects.toStringHelper(this)
//       .add("userId", userId)
//       .add("tenantId", tenantId)
//       .toString();
//   }
// }
// 
// Path: coopr-server/src/main/java/co/cask/coopr/scheduler/task/MissingEntityException.java
// public class MissingEntityException extends Exception {
// 
//   /**
//    * New exception with error message.
//    * @param message the error message
//    */
//   public MissingEntityException(String message) {
//     super(message);
//   }
// 
//   public MissingEntityException(String message, Throwable cause) {
//     super(message, cause);
//   }
// 
//   public MissingEntityException(Throwable cause) {
//     super(cause);
//   }
// }
// 
// Path: coopr-server/src/main/java/co/cask/coopr/store/entity/EntityStoreService.java
// public interface EntityStoreService extends Service {
// 
//   /**
//    * Get a view of the entity store as seen by the given account.
//    *
//    * @param account Account that will be viewing the entity store
//    * @return view of the entity store as seen by the given account.
//    */
//   EntityStoreView getView(Account account);
// 
//   /**
//    * Copy all entities from one account to another. Overwrites existing entities in target account if they already
//    * exist. This operation is not atomic, and should be used only in specific circumstances, such as when bootstrapping
//    * a new, empty account.
//    *
//    * @param from Account to copy from
//    * @param to Account to copy to
//    * @throws IOException if there was a problem copying the entities
//    */
//   void copyEntities(Account from, Account to) throws IOException, IllegalAccessException;
// }


import co.cask.coopr.account.Account;
import co.cask.coopr.common.conf.Constants;
import co.cask.coopr.provisioner.TenantProvisionerService;
import co.cask.coopr.provisioner.plugin.PluginType;
import co.cask.coopr.provisioner.plugin.ResourceMeta;
import co.cask.coopr.provisioner.plugin.ResourceService;
import co.cask.coopr.provisioner.plugin.ResourceStatus;
import co.cask.coopr.provisioner.plugin.ResourceType;
import co.cask.coopr.scheduler.task.MissingEntityException;
import co.cask.coopr.spec.plugin.AbstractPluginSpecification;
import co.cask.coopr.store.entity.EntityStoreService;
import co.cask.coopr.store.tenant.TenantStore;
import co.cask.http.BodyConsumer;
import co.cask.http.HttpResponder;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.google.inject.Inject;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;
import org.jboss.netty.handler.codec.http.QueryStringDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
/*
 * Copyright © 2012-2014 Cask Data, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package co.cask.coopr.http.handler;



/**
 * Handler for plugin resource related operations, such as uploading resources, staging, and recalling resources,
 * and syncing resources. Only a tenant admin can access these APIs.
 */
@Path(Constants.API_BASE + "/plugins")
public class PluginHandler extends AbstractAuthHandler {
  private static final Logger LOG  = LoggerFactory.getLogger(PluginHandler.class);
  private final Gson gson;
  private final ResourceService resourceService;
// Path: coopr-server/src/main/java/co/cask/coopr/account/Account.java
// public final class Account {
//   public static final Account SUPERADMIN = new Account(Constants.ADMIN_USER, Constants.SUPERADMIN_TENANT);
//   private final String userId;
//   private final String tenantId;
// 
//   public Account(String userId, String tenantId) {
//     Preconditions.checkArgument(userId != null && !userId.isEmpty(), "Account must have a user id.");
//     Preconditions.checkArgument(tenantId != null && !tenantId.isEmpty(), "Account must have a tenant id.");
//     this.userId = userId;
//     this.tenantId = tenantId;
//   }
// 
//   public String getUserId() {
//     return userId;
//   }
// 
//   public String getTenantId() {
//     return tenantId;
//   }
// 
//   public boolean isAdmin() {
//     return Constants.ADMIN_USER.equals(userId);
//   }
// 
//   public boolean isSuperadmin() {
//     return Constants.ADMIN_USER.equals(userId) && Constants.SUPERADMIN_TENANT.equals(tenantId);
//   }
// 
//   @Override
//   public boolean equals(Object o) {
//     if (this == o) {
//       return true;
//     }
//     if (!(o instanceof Account)) {
//       return false;
//     }
// 
//     Account other = (Account) o;
//     return Objects.equal(userId, other.userId) &&
//       Objects.equal(tenantId, other.tenantId);
//   }
// 
//   @Override
//   public int hashCode() {
//     return Objects.hashCode(userId, tenantId);
//   }
// 
//   @Override
//   public String toString() {
//     return Objects.toStringHelper(this)
//       .add("userId", userId)
//       .add("tenantId", tenantId)
//       .toString();
//   }
// }
// 
// Path: coopr-server/src/main/java/co/cask/coopr/scheduler/task/MissingEntityException.java
// public class MissingEntityException extends Exception {
// 
//   /**
//    * New exception with error message.
//    * @param message the error message
//    */
//   public MissingEntityException(String message) {
//     super(message);
//   }
// 
//   public MissingEntityException(String message, Throwable cause) {
//     super(message, cause);
//   }
// 
//   public MissingEntityException(Throwable cause) {
//     super(cause);
//   }
// }
// 
// Path: coopr-server/src/main/java/co/cask/coopr/store/entity/EntityStoreService.java
// public interface EntityStoreService extends Service {
// 
//   /**
//    * Get a view of the entity store as seen by the given account.
//    *
//    * @param account Account that will be viewing the entity store
//    * @return view of the entity store as seen by the given account.
//    */
//   EntityStoreView getView(Account account);
// 
//   /**
//    * Copy all entities from one account to another. Overwrites existing entities in target account if they already
//    * exist. This operation is not atomic, and should be used only in specific circumstances, such as when bootstrapping
//    * a new, empty account.
//    *
//    * @param from Account to copy from
//    * @param to Account to copy to
//    * @throws IOException if there was a problem copying the entities
//    */
//   void copyEntities(Account from, Account to) throws IOException, IllegalAccessException;
// }


// Path: coopr-server/src/main/java/co/cask/coopr/http/handler/PluginHandler.java
import co.cask.coopr.account.Account;
import co.cask.coopr.common.conf.Constants;
import co.cask.coopr.provisioner.TenantProvisionerService;
import co.cask.coopr.provisioner.plugin.PluginType;
import co.cask.coopr.provisioner.plugin.ResourceMeta;
import co.cask.coopr.provisioner.plugin.ResourceService;
import co.cask.coopr.provisioner.plugin.ResourceStatus;
import co.cask.coopr.provisioner.plugin.ResourceType;
import co.cask.coopr.scheduler.task.MissingEntityException;
import co.cask.coopr.spec.plugin.AbstractPluginSpecification;
import co.cask.coopr.store.entity.EntityStoreService;
import co.cask.coopr.store.tenant.TenantStore;
import co.cask.http.BodyConsumer;
import co.cask.http.HttpResponder;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.google.inject.Inject;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;
import org.jboss.netty.handler.codec.http.QueryStringDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;

/*
 * Copyright © 2012-2014 Cask Data, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package co.cask.coopr.http.handler;



/**
 * Handler for plugin resource related operations, such as uploading resources, staging, and recalling resources,
 * and syncing resources. Only a tenant admin can access these APIs.
 */
@Path(Constants.API_BASE + "/plugins")
public class PluginHandler extends AbstractAuthHandler {
  private static final Logger LOG  = LoggerFactory.getLogger(PluginHandler.class);
  private final Gson gson;
  private final ResourceService resourceService;
  private final EntityStoreService entityStoreService;