blob: 428a1df0df53eb67e2bc446a7b71ed782625a1a2 [file] [log] [blame]
/*******************************************************************************
* 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
}
}