/******************************************************************************* * 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.core.NotFoundException; import org.eclipse.che.api.user.server.dao.Profile; import org.eclipse.che.api.user.server.dao.UserProfileDao; import com.google.common.io.Files; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.Nullable; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; import java.io.File; import java.io.IOException; import java.io.Reader; import java.io.Writer; import java.nio.charset.Charset; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; @Singleton public class LocalProfileDaoImpl implements UserProfileDao { private static final Logger LOG = LoggerFactory.getLogger(LocalProfileDaoImpl.class); private final File storageFile; private final Gson gson; private final Map<String, Profile> profiles; private final ReadWriteLock lock; @Inject public LocalProfileDaoImpl(@Nullable @Named("profile.store_location") String dirPath) { if (dirPath == null || dirPath.isEmpty()) { storageFile = new File(System.getProperty("java.io.tmpdir"), "ProfileStorage.json"); } else { storageFile = new File(dirPath, "ProfileStorage.json"); } gson = new Gson(); profiles = new HashMap<>(); lock = new ReentrantReadWriteLock(); } @PostConstruct private void start() { // use write lock since we are validate storage at this stage lock.writeLock().lock(); try { if (storageFile.exists()) { Reader reader = null; try { reader = Files.newReader(storageFile, Charset.forName("UTF-8")); Map<String, Profile> m = gson.fromJson(reader, new TypeToken<Map<String, Profile>>() { }.getType()); if (m != null) { profiles.putAll(m); } } catch (Exception e) { LOG.error(String.format("Failed load user profiles form %s", storageFile), e); } finally { if (reader != null) { try { reader.close(); } catch (IOException ignored) { } } } } // Add default entry if file doesn't exist or invalid or empty. if (profiles.isEmpty()) { final Map<String, String> attributes = new HashMap<>(2); attributes.put("First Name", "Codenvy"); attributes.put("Last Name", "Codenvy"); Profile profile = new Profile().withId("codenvy") .withUserId("codenvy") .withAttributes(attributes); profiles.put(profile.getId(), profile); } } finally { lock.writeLock().unlock(); } } @PreDestroy private void stop() { lock.writeLock().lock(); try { Writer writer = null; try { writer = Files.newWriter(storageFile, Charset.forName("UTF-8")); gson.toJson(profiles, new TypeToken<Map<String, Profile>>() { }.getType(), writer); } catch (Exception e) { LOG.error(String.format("Failed setPreferences user profiles form %s", storageFile), e); } finally { if (writer != null) { try { writer.close(); } catch (IOException e) { LOG.error(String.format("Failed setPreferences user profiles form %s", storageFile), e); } } } } finally { lock.writeLock().unlock(); } } @Override public void create(Profile profile) { lock.writeLock().lock(); try { // just replace existed profile final Profile copy = new Profile().withId(profile.getId()).withUserId(profile.getUserId()) .withAttributes(new LinkedHashMap<>(profile.getAttributes())); profiles.put(copy.getId(), copy); } finally { lock.writeLock().unlock(); } } @Override public void update(Profile profile) throws NotFoundException { lock.writeLock().lock(); try { final Profile myProfile = profiles.get(profile.getId()); if (myProfile == null) { throw new NotFoundException(String.format("Profile not found %s", profile.getId())); } myProfile.getAttributes().clear(); myProfile.getAttributes().putAll(profile.getAttributes()); } finally { lock.writeLock().unlock(); } } @Override public void remove(String id) throws NotFoundException { lock.writeLock().lock(); try { final Profile profile = profiles.remove(id); if (profile == null) { throw new NotFoundException(String.format("Profile not found %s", id)); } } finally { lock.writeLock().unlock(); } } @Override public Profile getById(String id) throws NotFoundException { lock.readLock().lock(); try { final Profile profile = profiles.get(id); if (profile == null) { throw new NotFoundException(String.format("Profile not found %s", id)); } return new Profile().withId(profile.getId()).withUserId(profile.getUserId()) .withAttributes(new LinkedHashMap<>(profile.getAttributes())); } finally { lock.readLock().unlock(); } } }