| /******************************************************************************* |
| * Copyright (c) 2004, 2012 Tasktop Technologies and others. |
| * 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: |
| * Tasktop Technologies - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.mylyn.tasks.core; |
| |
| import java.io.BufferedOutputStream; |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.ObjectInputStream; |
| import java.io.ObjectOutputStream; |
| import java.io.ObjectStreamClass; |
| import java.io.Serializable; |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.mylyn.commons.core.StatusHandler; |
| import org.eclipse.mylyn.internal.tasks.core.ITasksCoreConstants; |
| |
| /** |
| * @author Steffen Pingel |
| * @author Benjamin Muskalla |
| * @since 3.8 |
| */ |
| public abstract class RepositoryClientManager<T, C extends Serializable> implements IRepositoryListener { |
| |
| /** |
| * Delegates to <code>repositoryConfigurationClass</code>'s class loader for accessing classes. |
| */ |
| private class OsgiAwareObjectInputStream extends ObjectInputStream { |
| |
| public OsgiAwareObjectInputStream(InputStream in) throws IOException { |
| super(in); |
| } |
| |
| @Override |
| protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { |
| try { |
| return Class.forName(desc.getName(), true, repositoryConfigurationClass.getClassLoader()); |
| } catch (Exception e) { |
| return super.resolveClass(desc); |
| } |
| } |
| |
| } |
| |
| private final Map<String, T> clientByUrl = new HashMap<String, T>(); |
| |
| private final Map<String, C> respoitoryConfigurationByUrl = new HashMap<String, C>(); |
| |
| private final File cacheFile; |
| |
| private TaskRepositoryLocationFactory locationFactory; |
| |
| private final Class<C> repositoryConfigurationClass; |
| |
| public RepositoryClientManager(File cacheFile, Class<C> repositoryConfigurationClass) { |
| Assert.isNotNull(cacheFile); |
| this.cacheFile = cacheFile; |
| this.repositoryConfigurationClass = repositoryConfigurationClass; |
| readCache(); |
| } |
| |
| public synchronized T getClient(TaskRepository repository) { |
| Assert.isNotNull(repository); |
| T client = clientByUrl.get(repository.getRepositoryUrl()); |
| if (client == null) { |
| C data = respoitoryConfigurationByUrl.get(repository.getRepositoryUrl()); |
| if (data == null) { |
| data = createRepositoryConfiguration(repository); |
| respoitoryConfigurationByUrl.put(repository.getRepositoryUrl(), data); |
| } |
| |
| client = createClient(repository, data); |
| clientByUrl.put(repository.getRepositoryUrl(), client); |
| } |
| return client; |
| } |
| |
| protected C createRepositoryConfiguration(TaskRepository repository) { |
| try { |
| return repositoryConfigurationClass.newInstance(); |
| } catch (Exception e) { |
| throw new RuntimeException(e); |
| } |
| } |
| |
| protected abstract T createClient(TaskRepository taskRepository, C data); |
| |
| public void repositoriesRead() { |
| // ignore |
| } |
| |
| public synchronized void repositoryAdded(TaskRepository repository) { |
| removeClient(repository); |
| respoitoryConfigurationByUrl.remove(repository.getRepositoryUrl()); |
| } |
| |
| private void removeClient(TaskRepository repository) { |
| clientByUrl.remove(repository.getRepositoryUrl()); |
| } |
| |
| public synchronized void repositoryRemoved(TaskRepository repository) { |
| removeClient(repository); |
| respoitoryConfigurationByUrl.remove(repository.getRepositoryUrl()); |
| } |
| |
| public synchronized void repositorySettingsChanged(TaskRepository repository) { |
| removeClient(repository); |
| } |
| |
| @SuppressWarnings("unchecked") |
| public void readCache() { |
| if (cacheFile == null || !cacheFile.exists()) { |
| return; |
| } |
| |
| ObjectInputStream in = null; |
| try { |
| in = new OsgiAwareObjectInputStream(new FileInputStream(cacheFile)); |
| int size = in.readInt(); |
| for (int i = 0; i < size; i++) { |
| String url = (String) in.readObject(); |
| C data = (C) in.readObject(); |
| if (url != null && data != null) { |
| respoitoryConfigurationByUrl.put(url, data); |
| } |
| } |
| } catch (Throwable e) { |
| handleError("The respository configuration cache could not be read", e); //$NON-NLS-1$ |
| } finally { |
| if (in != null) { |
| try { |
| in.close(); |
| } catch (IOException e) { |
| // ignore |
| } |
| } |
| } |
| |
| } |
| |
| protected void handleError(String message, Throwable e) { |
| StatusHandler.log(new Status(IStatus.WARNING, ITasksCoreConstants.ID_PLUGIN, message, e)); |
| } |
| |
| public void writeCache() { |
| if (cacheFile == null) { |
| return; |
| } |
| |
| try (ObjectOutputStream out = new ObjectOutputStream( |
| new BufferedOutputStream(new FileOutputStream(cacheFile)))) { |
| out.writeInt(respoitoryConfigurationByUrl.size()); |
| for (String url : respoitoryConfigurationByUrl.keySet()) { |
| out.writeObject(url); |
| out.writeObject(respoitoryConfigurationByUrl.get(url)); |
| } |
| } catch (IOException e) { |
| handleError("The respository configuration cache could not be written", e); //$NON-NLS-1$ |
| } |
| } |
| |
| public TaskRepositoryLocationFactory getLocationFactory() { |
| return locationFactory; |
| } |
| |
| public void setLocationFactory(TaskRepositoryLocationFactory locationFactory) { |
| this.locationFactory = locationFactory; |
| } |
| |
| public void repositoryUrlChanged(TaskRepository repository, String oldUrl) { |
| // ignore |
| } |
| |
| } |