/*
GanttProject is an opensource project management tool. License: GPL3
Copyright (C) 2012 GanttProject Team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 3
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package net.sourceforge.ganttproject.document.webdav;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import javax.swing.Action;
import javax.swing.JComponent;
import net.sourceforge.ganttproject.GPLogger;
import net.sourceforge.ganttproject.IGanttProject;
import net.sourceforge.ganttproject.ProjectEventListener;
import net.sourceforge.ganttproject.action.CancelAction;
import net.sourceforge.ganttproject.action.OkAction;
import net.sourceforge.ganttproject.document.Document;
import net.sourceforge.ganttproject.document.DocumentStorageUi;
import net.sourceforge.ganttproject.gui.UIFacade;
import biz.ganttproject.core.option.BooleanOption;
import biz.ganttproject.core.option.ChangeValueEvent;
import biz.ganttproject.core.option.ChangeValueListener;
import biz.ganttproject.core.option.DefaultBooleanOption;
import biz.ganttproject.core.option.DefaultEnumerationOption;
import biz.ganttproject.core.option.DefaultIntegerOption;
import biz.ganttproject.core.option.DefaultStringOption;
import biz.ganttproject.core.option.EnumerationOption;
import biz.ganttproject.core.option.GPAbstractOption;
import biz.ganttproject.core.option.IntegerOption;
import biz.ganttproject.core.option.ListOption;
import biz.ganttproject.core.option.StringOption;
import com.google.common.base.Objects;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
/**
* Implements storage UI for WebDAV storages
*
* @author dbarashev (Dmitry Barashev)
*/
public class WebDavStorageImpl implements DocumentStorageUi {
static class ServerListOption extends GPAbstractOption<WebDavServerDescriptor> implements ListOption<WebDavServerDescriptor> {
private List<WebDavServerDescriptor> myServers = Lists.newArrayList();
class EnumerationOptionImpl extends DefaultEnumerationOption<WebDavServerDescriptor> {
public EnumerationOptionImpl(String id) {
super(id, myServers.toArray(new WebDavServerDescriptor[0]));
}
@Override
protected String objectToString(WebDavServerDescriptor obj) {
return obj.name;
}
@Override
public void setValue(String value) {
super.setValue(value);
ServerListOption.this.setValue(stringToObject(value));
}
void reload() {
String curValue = getValue();
int idxValue = Arrays.asList(getAvailableValues()).indexOf(curValue);
super.reloadValues(myServers);
if (idxValue >= 0) {
setValueIndex(idxValue);
}
}
};
private EnumerationOptionImpl myEnumerationOption;
public ServerListOption(String id) {
super(id);
myEnumerationOption = new EnumerationOptionImpl(id);
}
@Override
public String getPersistentValue() {
StringBuilder result = new StringBuilder();
for (WebDavServerDescriptor server : myServers) {
result.append("\n").append(server.name).append("\t").append(server.getRootUrl()).append("\t").append(server.username);
if (server.savePassword) {
result.append("\t").append(server.password);
}
}
return result.toString();
}
@Override
public void loadPersistentValue(String value) {
for (String s : value.split("\\n")) {
if (!Strings.isNullOrEmpty(s)) {
String[] parts = s.split("\\t");
WebDavServerDescriptor server = new WebDavServerDescriptor();
if (parts.length >= 1) {
server.name = parts[0];
}
if (parts.length >= 2) {
server.setRootUrl(parts[1]);
}
if (parts.length >= 3) {
server.username = parts[2];
}
if (parts.length >= 4) {
server.password = parts[3];
server.savePassword = true;
}
myServers.add(server);
}
}
myEnumerationOption.reload();
}
@Override
public void setValues(Iterable<WebDavServerDescriptor> values) {
myServers = Lists.newArrayList(values);
myEnumerationOption.reload();
}
@Override
public Iterable<WebDavServerDescriptor> getValues() {
return myServers;
}
@Override
public void setValueIndex(int idx) {
super.setValue(myServers.get(idx));
}
@Override
public void setValue(WebDavServerDescriptor value) {
if (!Objects.equal(value, getValue())) {
super.setValue(value);
myEnumerationOption.setSelectedValue(value);
}
}
@Override
public void addValue(WebDavServerDescriptor value) {
myServers.add(value);
myEnumerationOption.reload();
}
@Override
public void updateValue(WebDavServerDescriptor oldValue, WebDavServerDescriptor newValue) {
int idxOldValue = myServers.indexOf(oldValue);
assert idxOldValue >= 0 : "Failed to find value=" + oldValue + " in the list=" + myServers;
myServers.set(idxOldValue, newValue);
myEnumerationOption.reload();
}
@Override
public void removeValueIndex(int idx) {
myServers.remove(idx);
myEnumerationOption.reload();
}
@Override
public EnumerationOption asEnumerationOption() {
return myEnumerationOption;
}
}
private final ListOption<WebDavServerDescriptor> myServers = new ServerListOption("servers");
private final StringOption myLegacyLastWebDAVDocument = new DefaultStringOption("last-webdav-document", "");
private final StringOption myLastWebDavDocumentOption = new DefaultStringOption("lastDocument", null);
private final IntegerOption myWebDavLockTimeoutOption = new DefaultIntegerOption("webdav.lockTimeout", -1);
private final BooleanOption myReleaseLockOption = new DefaultBooleanOption("lockRelease", true);
private final StringOption myUsername = new DefaultStringOption("username", "");
private final StringOption myPassword = new DefaultStringOption("password", "");
private final StringOption myProxy = new DefaultStringOption("proxy", "");
private final MiltonResourceFactory myWebDavFactory = new MiltonResourceFactory();
private final UIFacade myUiFacade;
private final IGanttProject myProject;
public WebDavStorageImpl(final IGanttProject project, UIFacade uiFacade) {
myProject = project;
myUiFacade = uiFacade;
project.addProjectEventListener(new ProjectEventListener.Stub() {
@Override
public void projectClosed() {
if (myReleaseLockOption.isChecked() && project.getDocument() != null) {
project.getDocument().releaseLock();
}
}
});
myPassword.setScreened(true);
}
@Override
public Components open(Document currentDocument, final DocumentReceiver receiver) {
final GanttURLChooser chooser = createChooser(currentDocument);
final OkAction openAction = createNoLockAction("storage.action.open", chooser, receiver);
//final OkAction openAndLockAction = createLockAction("storage.action.openAndLock", chooser, receiver);
// chooser.setSelectionListener(new GanttURLChooser.SelectionListener() {
// @Override
// public void setSelection(WebDavResource resource) {
// if (resource == null) {
// return;
// }
// try {
// openAndLockAction.setEnabled(resource.canLock());
// } catch (WebDavException e) {
// chooser.showError(e);
// }
// }
// });
JComponent contentPane = chooser.createOpenDocumentUi(openAction);
chooser.getPathOption().addChangeValueListener(new ChangeValueListener() {
@Override
public void changeValue(ChangeValueEvent event) {
boolean empty = "".equals(event.getNewValue());
openAction.setEnabled(!empty);
// openAndLockAction.setEnabled(!empty);
}
});
return new Components(contentPane, new Action[] {openAction, /*openAndLockAction,*/ new CancelAction() {
@Override
public void actionPerformed(ActionEvent e) {
receiver.setDocument(null);
}
}});
}
@Override
public Components save(Document currentDocument, final DocumentReceiver receiver) {
final GanttURLChooser chooser = createChooser(currentDocument);
OkAction saveAction = createNoLockAction("storage.action.save", chooser, receiver);
JComponent contentPane = chooser.createSaveDocumentUi(saveAction);
return new Components(contentPane, new Action[] {saveAction, new CancelAction() {
@Override
public void actionPerformed(ActionEvent e) {
receiver.setDocument(null);
}
}});
}
private GanttURLChooser createChooser(Document currentDocument) {
WebDavUri currentUri;
if (currentDocument instanceof HttpDocument) {
currentUri = ((HttpDocument)currentDocument).getWebdavResource().getWebDavUri();
myUsername.setValue(currentDocument.getUsername());
myPassword.setValue(currentDocument.getPassword());
} else {
String lastDocument = Objects.firstNonNull(
getLastWebDavDocumentOption().getValue(), getLegacyLastWebDAVDocumentOption().getValue());
if (lastDocument == null) {
currentUri = null;
} else {
String[] savedComponents = lastDocument.split("\\t");
if (savedComponents.length == 1) {
currentUri = new WebDavUri(savedComponents[0]);
} else {
try {
URL rootUrl = new URL(savedComponents[0]);
currentUri = new WebDavUri(rootUrl.getHost(), savedComponents[0], savedComponents[1]);
} catch (MalformedURLException e) {
GPLogger.logToLogger(e);
currentUri = null;
}
}
}
}
myWebDavFactory.clearCache();
return new GanttURLChooser(myProject, myUiFacade, myServers, currentUri, myUsername, myPassword, getWebDavLockTimeoutOption(), getWebDavReleaseLockOption(), myWebDavFactory);
}
private OkAction createNoLockAction(String key, final GanttURLChooser chooser, final DocumentReceiver receiver) {
return new OkAction(key) {
{
setDefault(false);
}
@Override
public void actionPerformed(ActionEvent event) {
try {
myWebDavFactory.setCredentials(chooser.getUsername(), chooser.getPassword());
WebDavUri webDavUri = chooser.getUrl();
if (webDavUri != null) {
receiver.setDocument(new HttpDocument(
myWebDavFactory.createResource(webDavUri), chooser.getUsername(), chooser.getPassword(), HttpDocument.NO_LOCK));
myLastWebDavDocumentOption.setValue(webDavUri.buildRootUrl() + "\t" + webDavUri.path);
myLegacyLastWebDAVDocument.setValue(webDavUri.buildUrl());
}
chooser.dispose();
} catch (IOException e) {
chooser.showError(e);
}
}
};
}
public ListOption<WebDavServerDescriptor> getServersOption() {
return myServers;
}
public StringOption getWebDavUsernameOption() {
return myUsername;
}
public StringOption getLegacyLastWebDAVDocumentOption() {
return myLegacyLastWebDAVDocument;
}
public StringOption getLastWebDavDocumentOption() {
return myLastWebDavDocumentOption;
}
public IntegerOption getWebDavLockTimeoutOption() {
return myWebDavLockTimeoutOption;
}
public BooleanOption getWebDavReleaseLockOption() {
return myReleaseLockOption;
}
public WebDavServerDescriptor findServer(String path) {
WebDavUri uri = new WebDavUri(path);
for (WebDavServerDescriptor server : myServers.getValues()) {
if (server.getRootUrl().equals(uri.buildRootUrl())) {
return server;
}
}
return null;
}
public StringOption getProxyOption () {
return myProxy;
}
}