/******************************************************************************* * Copyright (c) 2012-2015 Codenvy, S.A. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Codenvy, S.A. - initial API and implementation *******************************************************************************/ package org.eclipse.che.api.local; import org.eclipse.che.api.account.server.dao.Account; import org.eclipse.che.api.account.server.dao.AccountDao; import org.eclipse.che.api.account.server.dao.Member; import org.eclipse.che.api.account.server.dao.Subscription; import org.eclipse.che.api.account.server.dao.SubscriptionQueryBuilder; import org.eclipse.che.api.core.ConflictException; import org.eclipse.che.api.core.ForbiddenException; import org.eclipse.che.api.core.NotFoundException; import org.eclipse.che.api.core.ServerException; import org.eclipse.che.api.workspace.server.dao.WorkspaceDao; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Set; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import static org.eclipse.che.api.account.shared.dto.SubscriptionState.ACTIVE; /** * @author Eugene Voevodin */ @Singleton public class LocalAccountDaoImpl implements AccountDao { private final List<Account> accounts; private final List<Member> members; private final List<Subscription> subscriptions; private final ReadWriteLock lock; private final WorkspaceDao workspaceDao; @Inject public LocalAccountDaoImpl(@Named("codenvy.local.infrastructure.accounts") Set<Account> accounts, @Named("codenvy.local.infrastructure.account.members") Set<Member> members, @Named("codenvy.local.infrastructure.account.subscriptions") Set<Subscription> subscriptions, WorkspaceDao workspaceDao) { this.workspaceDao = workspaceDao; this.accounts = new LinkedList<>(); this.members = new LinkedList<>(); this.subscriptions = new LinkedList<>(); lock = new ReentrantReadWriteLock(); try { for (Account account : accounts) { create(account); } for (Member member : members) { addMember(member); } for (Subscription subscription : subscriptions) { addSubscription(subscription); } } catch (Exception e) { // fail if can't validate this instance properly throw new RuntimeException(e); } } @Override public void create(Account account) throws ConflictException { lock.writeLock().lock(); try { for (Account a : accounts) { if (a.getId().equals(account.getId())) { throw new ConflictException(String.format("Account with id %s already exists.", account.getId())); } if (a.getName().equals(account.getName())) { throw new ConflictException(String.format("Account with name %s already exists.", account.getName())); } } accounts.add(new Account().withId(account.getId()).withName(account.getName()) .withAttributes(new LinkedHashMap<>(account.getAttributes()))); } finally { lock.writeLock().unlock(); } } @Override public Account getById(String id) throws NotFoundException { lock.readLock().lock(); try { for (Account account : accounts) { if (account.getId().equals(id)) { return new Account().withId(account.getId()).withName(account.getName()) .withAttributes(new LinkedHashMap<>(account.getAttributes())); } } } finally { lock.readLock().unlock(); } throw new NotFoundException(String.format("Not found account %s", id)); } @Override public Account getByName(String name) throws NotFoundException { lock.readLock().lock(); try { for (Account account : accounts) { if (account.getName().equals(name)) { return new Account().withId(account.getId()).withName(account.getName()) .withAttributes(new LinkedHashMap<>(account.getAttributes())); } } } finally { lock.readLock().unlock(); } throw new NotFoundException(String.format("Not found account %s", name)); } @Override public List<Account> getByOwner(String owner) { final List<Account> result = new LinkedList<>(); lock.readLock().lock(); try { for (Member member : members) { if (member.getUserId().equals(owner)) { for (Account account : accounts) { if (account.getId().equals(member.getAccountId()) && member.getRoles().contains("account/owner")) { result.add(new Account().withId(account.getId()).withName(account.getName()) .withAttributes(new LinkedHashMap<>(account.getAttributes()))); } } } } } finally { lock.readLock().unlock(); } return result; } @Override public List<Member> getByMember(String userId) { final List<Member> result = new LinkedList<>(); lock.readLock().lock(); try { for (Member member : members) { if (userId.equals(member.getUserId())) { result.add(new Member().withUserId(member.getUserId()).withAccountId(member.getAccountId()) .withRoles(new ArrayList<>(member.getRoles()))); } } } finally { lock.readLock().unlock(); } return result; } @Override public void update(Account account) throws NotFoundException { lock.writeLock().lock(); try { Account myAccount = null; for (int i = 0, size = accounts.size(); i < size && myAccount == null; i++) { if (accounts.get(i).getId().equals(account.getId())) { myAccount = accounts.get(i); } } if (myAccount == null) { throw new NotFoundException(String.format("Not found account %s", account.getId())); } myAccount.setName(account.getName()); myAccount.getAttributes().clear(); myAccount.getAttributes().putAll(account.getAttributes()); } finally { lock.writeLock().unlock(); } } @Override public void remove(String id) throws NotFoundException, ServerException, ConflictException { lock.writeLock().lock(); try { Account myAccount = null; for (int i = 0, size = accounts.size(); i < size && myAccount == null; i++) { if (accounts.get(i).getId().equals(id)) { myAccount = accounts.get(i); } } if (myAccount == null) { throw new NotFoundException(String.format("Not found account %s", id)); } if (!workspaceDao.getByAccount(id).isEmpty()) { throw new ConflictException("It is not possible to remove account that has associated workspaces"); } for (Iterator<Member> itr = members.iterator(); itr.hasNext(); ) { final Member member = itr.next(); if (member.getAccountId().equals(id)) { itr.remove(); } } accounts.remove(myAccount); } finally { lock.writeLock().unlock(); } } @Override public void addMember(Member member) throws NotFoundException, ConflictException { lock.writeLock().lock(); try { Account myAccount = null; for (int i = 0, size = accounts.size(); i < size && myAccount == null; i++) { if (accounts.get(i).getId().equals(member.getAccountId())) { myAccount = accounts.get(i); } } if (myAccount == null) { throw new NotFoundException(String.format("Not found account %s", member.getAccountId())); } for (Member m : members) { if (m.getUserId().equals(member.getUserId()) && m.getAccountId().equals(member.getAccountId())) { throw new ConflictException(String.format("Membership of user %s in account %s already exists.", member.getUserId(), member.getAccountId()) ); } } members.add(new Member().withUserId(member.getUserId()).withAccountId(member.getAccountId()) .withRoles(new ArrayList<>(member.getRoles()))); } finally { lock.writeLock().unlock(); } } @Override public List<Member> getMembers(String accountId) { final List<Member> result = new LinkedList<>(); lock.readLock().lock(); try { for (Member member : members) { if (accountId.equals(member.getAccountId())) { result.add(new Member().withUserId(member.getUserId()).withAccountId(member.getAccountId()) .withRoles(new ArrayList<>(member.getRoles()))); } } } finally { lock.readLock().unlock(); } return result; } @Override public void removeMember(Member member) throws NotFoundException { lock.writeLock().lock(); try { Member myMember = null; for (int i = 0, size = members.size(); i < size && myMember == null; i++) { if (members.get(i).getUserId().equals(member.getUserId())) { myMember = members.get(i); } } if (myMember == null) { throw new NotFoundException(String.format("User with id %s hasn't any account membership", member.getUserId())); } Account myAccount = null; for (int i = 0, size = accounts.size(); i < size && myAccount == null; i++) { if (accounts.get(i).getId().equals(member.getAccountId())) { myAccount = accounts.get(i); } } if (myAccount == null) { throw new NotFoundException(String.format("Not found account %s", member.getAccountId())); } members.remove(myMember); } finally { lock.writeLock().unlock(); } } @Override public void addSubscription(Subscription subscription) throws NotFoundException { lock.writeLock().lock(); try { Account myAccount = null; for (int i = 0, size = accounts.size(); i < size && myAccount == null; i++) { if (accounts.get(i).getId().equals(subscription.getAccountId())) { myAccount = accounts.get(i); } } if (myAccount == null) { throw new NotFoundException(String.format("Not found account %s", subscription.getAccountId())); } subscriptions.add(new Subscription(subscription)); } finally { lock.writeLock().unlock(); } } @Override public void removeSubscription(String subscriptionId) throws NotFoundException { lock.writeLock().lock(); try { Subscription subscription = null; for (int i = 0, size = subscriptions.size(); i < size && subscription == null; i++) { if (subscriptions.get(i).getId().equals(subscriptionId)) { subscription = subscriptions.get(i); } } if (subscription == null) { throw new NotFoundException(String.format("Not found subscription %s", subscriptionId)); } subscriptions.remove(subscription); } finally { lock.writeLock().unlock(); } } @Override public Subscription getSubscriptionById(String subscriptionId) throws NotFoundException { lock.readLock().lock(); try { Subscription subscription = null; for (int i = 0, size = subscriptions.size(); i < size && subscription == null; i++) { if (subscriptions.get(i).getId().equals(subscriptionId)) { subscription = subscriptions.get(i); } } if (subscription == null) { throw new NotFoundException(String.format("Not found subscription %s", subscriptionId)); } return new Subscription(subscription); } finally { lock.readLock().unlock(); } } @Override public List<Subscription> getActiveSubscriptions(String accountId) { final List<Subscription> result = new LinkedList<>(); lock.readLock().lock(); try { for (Subscription subscription : subscriptions) { if (accountId.equals(subscription.getAccountId()) && ACTIVE.equals(subscription.getState())) { result.add(new Subscription(subscription)); } } } finally { lock.readLock().unlock(); } return result; } @Override public Subscription getActiveSubscription(String accountId, String serviceId) { lock.readLock().lock(); try { for (Subscription subscription : subscriptions) { if (accountId.equals(subscription.getAccountId()) && serviceId.equals(subscription.getServiceId()) && ACTIVE.equals(subscription.getState())) { return new Subscription(subscription); } } } finally { lock.readLock().unlock(); } return null; } @Override public void updateSubscription(Subscription subscription) throws NotFoundException, ServerException { lock.writeLock().lock(); try { int i = 0; Subscription mySubscription = null; for (int size = subscriptions.size(); i < size && mySubscription == null; i++) { if (subscriptions.get(i).getId().equals(subscription.getId())) { mySubscription = subscriptions.get(i); } } if (mySubscription == null) { throw new NotFoundException(String.format("Not found subscription %s", subscription.getId())); } subscriptions.remove(i); subscriptions.add(i, new Subscription(subscription)); } finally { lock.writeLock().unlock(); } } @Override public SubscriptionQueryBuilder getSubscriptionQueryBuilder() { throw new UnsupportedOperationException(); } @Override public List<Account> getAccountsWithLockedResources() throws ServerException, ForbiddenException { List<Account> lockedAccounts = new LinkedList<>(); for (Account account : accounts) { if (account.getAttributes().containsKey("codenvy:locked") && account.getAttributes().get("codenvy:locked").equals("true")) { lockedAccounts.add(account); } } return lockedAccounts; } }