Skip to content
This repository has been archived by the owner on Apr 10, 2024. It is now read-only.

Commit

Permalink
Added WebDav support
Browse files Browse the repository at this point in the history
  • Loading branch information
ZD committed Oct 21, 2010
1 parent c3ae1e1 commit 2572745
Show file tree
Hide file tree
Showing 16 changed files with 317 additions and 41 deletions.
12 changes: 12 additions & 0 deletions backend/pom.xml
Expand Up @@ -106,5 +106,17 @@
<groupId>net.sf.opencsv</groupId>
<artifactId>opencsv</artifactId>
</dependency>
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-webdav</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,62 @@
/*
* Copyright (c) 2009, GoodData Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided
* that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
* the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
* and the following disclaimer in the documentation and/or other materials provided with the distribution.
* * Neither the name of the GoodData Corporation nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package com.gooddata.integration.datatransfer;

import com.gooddata.exception.GdcUploadErrorException;
import com.gooddata.integration.rest.configuration.NamePasswordConfiguration;
import com.gooddata.util.FileUtil;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPSClient;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.log4j.Logger;

import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.security.NoSuchAlgorithmException;

/**
* GoodData FTP API Java wrapper
*
* @author zd <zd@gooddata.com>
* @version 1.0
*/
public interface GdcDataTransferAPI {


/**
* Transfers a local directory to the remote GDC server
* @param archiveName the name of the ZIP archive that is going to be transferred
* @throws IOException in case of IO issues
*/
public void transferDir(String archiveName) throws IOException;

/**
* GET the transfer logs from the server
* @param remoteDir the primary transfer directory that contains the logs
* @return Map with the log name and content
* @throws IOException in case of IO issues
*/
public Map<String, String> getTransferLogs(String remoteDir) throws IOException;
}
Expand Up @@ -24,6 +24,7 @@
package com.gooddata.integration.ftp;

import com.gooddata.exception.GdcUploadErrorException;
import com.gooddata.integration.datatransfer.GdcDataTransferAPI;
import com.gooddata.integration.rest.configuration.NamePasswordConfiguration;
import com.gooddata.util.FileUtil;
import org.apache.commons.net.ftp.FTPClient;
Expand All @@ -42,7 +43,7 @@
* @author zd <zd@gooddata.com>
* @version 1.0
*/
public class GdcFTPApiWrapper {
public class GdcFTPApiWrapper implements GdcDataTransferAPI {

private static Logger l = Logger.getLogger(GdcFTPApiWrapper.class);

Expand Down
Expand Up @@ -1699,6 +1699,8 @@ private static <T extends HttpMethod> T configureHttpMethod(T request) {
}




public static Logger getL() {
return l;
}
Expand Down
@@ -0,0 +1,192 @@
/*
* Copyright (c) 2009, GoodData Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided
* that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
* the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
* and the following disclaimer in the documentation and/or other materials provided with the distribution.
* * Neither the name of the GoodData Corporation nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package com.gooddata.integration.webdav;

import com.gooddata.exception.HttpMethodException;
import com.gooddata.exception.HttpMethodNoContentException;
import com.gooddata.exception.HttpMethodNotFinishedYetException;
import com.gooddata.integration.datatransfer.GdcDataTransferAPI;
import com.gooddata.integration.rest.configuration.NamePasswordConfiguration;
import com.gooddata.util.FileUtil;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
import org.apache.commons.httpclient.methods.PutMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.jackrabbit.webdav.DavConstants;
import org.apache.jackrabbit.webdav.DavException;
import org.apache.jackrabbit.webdav.MultiStatus;
import org.apache.jackrabbit.webdav.MultiStatusResponse;
import org.apache.jackrabbit.webdav.client.methods.MkColMethod;
import org.apache.jackrabbit.webdav.client.methods.MkWorkspaceMethod;
import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
import org.apache.log4j.Logger;

import java.io.*;
import java.util.HashMap;
import java.util.Map;

/**
* GoodData Webdav API Java wrapper
*
* @author zd <zd@gooddata.com>
* @version 1.0
*/
public class GdcWebDavApiWrapper implements GdcDataTransferAPI {

private static Logger l = Logger.getLogger(GdcWebDavApiWrapper.class);

protected static final String DEFAULT_ARCHIVE_NAME = "upload.zip";
protected static final String WEBDAV_URI = "/uploads/";

protected HttpClient client;
protected NamePasswordConfiguration config;

/**
* Constructs the GoodData WebDav API Java wrapper
*
* @param config NamePasswordConfiguration object with the GDC name and password configuration
*/
public GdcWebDavApiWrapper(NamePasswordConfiguration config) {
this.config = config;
client = new HttpClient();
Credentials creds = new UsernamePasswordCredentials(this.config.getUsername(), this.config.getPassword());
client.getState().setCredentials(AuthScope.ANY, creds);
}

/**
* WebDav transfers a local directory to the remote GDC WebDav server
* @param archiveName the name of the ZIP archive that is going to be transferred
* @throws java.io.IOException in case of IO issues
*/
public void transferDir(String archiveName) throws IOException {
l.debug("Transfering archive "+archiveName);
File file = new File(archiveName);
String dir = file.getName().split("\\.")[0];
MkColMethod mkdir = new MkColMethod(this.config.getUrl()+WEBDAV_URI+dir);
executeMethodOk(mkdir);
PutMethod put = new PutMethod(this.config.getUrl()+WEBDAV_URI+dir+"/"+DEFAULT_ARCHIVE_NAME);
RequestEntity requestEntity = new InputStreamRequestEntity(new FileInputStream(file));
put.setRequestEntity(requestEntity);
executeMethodOk(put);
l.debug("Transferred archive "+archiveName);
}

/**
* GET the transfer logs from the FTP server
* @param remoteDir the primary transfer directory that contains the logs
* @return Map with the log name and content
* @throws java.io.IOException in case of IO issues
*/
public Map<String, String> getTransferLogs(String remoteDir) throws IOException {
l.debug("Retrieveing transfer logs.");
Map<String,String> result = new HashMap<String,String>();
PropFindMethod ls = new PropFindMethod(this.config.getUrl()+WEBDAV_URI+remoteDir+"/", DavConstants.PROPFIND_PROPERTY_NAMES, 1);
String ret = executeMethodOk(ls);
String[] files = ret.split(",");
for(String file : files) {
if(file.endsWith(".log")) {
GetMethod get = new GetMethod(this.config.getUrl()+file);
String content = executeMethodOk(get);
result.put(file, content);
}
}
l.debug("Transfer logs retrieved.");
return result;
}

/**
* Executes HttpMethod and test if the response if 200(OK)
*
* @param method the HTTP method
* @return response body as String
* @throws com.gooddata.exception.HttpMethodException
*/
private String executeMethodOk(HttpMethod method) throws HttpMethodException {
try {
client.executeMethod(method);
if (method.getStatusCode() == HttpStatus.SC_OK) {
return method.getResponseBodyAsString();
} else if (method.getStatusCode() == HttpStatus.SC_CREATED) {
return method.getResponseBodyAsString();
} else if (method.getStatusCode() == HttpStatus.SC_ACCEPTED) {
throw new HttpMethodNotFinishedYetException(method.getResponseBodyAsString());
} else if (method.getStatusCode() == HttpStatus.SC_NO_CONTENT) {
throw new HttpMethodNoContentException(method.getResponseBodyAsString());
} else if (method.getStatusCode() == HttpStatus.SC_MULTI_STATUS) {
if(method instanceof PropFindMethod) {
PropFindMethod ls = (PropFindMethod)method;
MultiStatus m = ls.getResponseBodyAsMultiStatus();
MultiStatusResponse[] responses = m.getResponses();
String resp = "";
for(MultiStatusResponse r : responses) {
if(resp.length() == 0)
resp = r.getHref();
else
resp += ","+r.getHref();
}
return resp;
}
else {
throw new HttpMethodException("Error invoking GoodData WebDav API. MultiStatus from non PROPFIND method.");
}
}else {
String msg = method.getStatusCode() + " " + method.getStatusText();
String body = method.getResponseBodyAsString();
if (body != null) {
msg += ": ";
try {
JSONObject parsedBody = JSONObject.fromObject(body);
msg += parsedBody.toString();
} catch (JSONException jsone) {
msg += body;
}
}
l.debug("Exception executing " + method.getName() + " on " + method.getPath() + ": " + msg);
throw new HttpMethodException("Exception executing " + method.getName() + " on " + method.getPath() + ": " + msg);
}
} catch (HttpException e) {
l.debug("Error invoking GoodData WebDav API.",e);
throw new HttpMethodException("Error invoking GoodData WebDav API.",e);
} catch (IOException e) {
l.debug("Error invoking GoodData REST API.",e);
throw new HttpMethodException("Error invoking GoodData WebDav API.",e);
} catch (DavException e) {
l.debug("Error invoking GoodData REST API.",e);
throw new HttpMethodException("Error invoking GoodData WebDav API.",e);
}
}


public static void main(String[] args) throws Exception {
NamePasswordConfiguration c = new NamePasswordConfiguration("https", "master.dev.getgooddata.com", "zd@gooddata.com", "jindrisska");
GdcWebDavApiWrapper w = new GdcWebDavApiWrapper(c);
Map<String,String> m = w.getTransferLogs("1116db8a-da6a-49b7-989c-31c51d8dd47b");
System.err.println(m);
}

}
Expand Up @@ -28,9 +28,11 @@
import com.gooddata.exception.InvalidArgumentException;
import com.gooddata.exception.InvalidCommandException;
import com.gooddata.exception.InvalidParameterException;
import com.gooddata.integration.datatransfer.GdcDataTransferAPI;
import com.gooddata.integration.ftp.GdcFTPApiWrapper;
import com.gooddata.integration.rest.GdcRESTApiWrapper;
import com.gooddata.integration.rest.configuration.NamePasswordConfiguration;
import com.gooddata.integration.webdav.GdcWebDavApiWrapper;
import org.apache.log4j.Logger;
import org.apache.log4j.MDC;

Expand All @@ -47,7 +49,7 @@ public class ProcessingContext {
private String projectId;
private Connector connector;
private GdcRESTApiWrapper _restApi = null;
private GdcFTPApiWrapper _ftpApi = null;
private GdcDataTransferAPI _ftpApi = null;


public String getProjectId() throws InvalidParameterException {
Expand Down Expand Up @@ -103,12 +105,14 @@ public GdcRESTApiWrapper getRestApi(CliParams cliParams) throws GdcLoginExceptio
return _restApi;
}

public GdcFTPApiWrapper getFtpApi(CliParams cliParams) {
public GdcDataTransferAPI getFtpApi(CliParams cliParams) {
if (_ftpApi == null) {
NamePasswordConfiguration ftpConfig = cliParams.getFtpConfig();
//TODO: Webdav vs. FTP
checkConfig(ftpConfig);
l.debug("Using the GoodData FTP host '" + ftpConfig.getGdcHost() + "'.");
_ftpApi = new GdcFTPApiWrapper(ftpConfig);
//_ftpApi = new GdcWebDavApiWrapper(ftpConfig);
}
return _ftpApi;
}
Expand Down
10 changes: 8 additions & 2 deletions cli-distro/bin/test.sh
Expand Up @@ -43,7 +43,7 @@ echo 'Running sfdc demo'
bin/gdi.sh examples/sfdc/sfdc.txt

echo 'Dropping the sfdc project and snapshots'
drop "`cat examples/sfdc/pid`"
drop "`cat examples/sfdc/pid`" c

echo 'Running jdbc demo'
bin/gdi.sh examples/jdbc/fundamentals.txt
Expand All @@ -52,11 +52,17 @@ echo 'Dropping the jdbc project and snapshots'
drop "`cat examples/jdbc/pid`"

echo 'Running ga demo'
bin/gdi.sh examples/ga/ga.txt
bin/gdi.sh examples/ga/cmd.create.txt

echo 'Dropping the ga project and snapshots'
drop "`cat examples/ga/pid`"

echo 'Running pt demo'
bin/gdi.sh examples/pt/cmd.txt

echo 'Dropping the pt project and snapshots'
drop "`cat examples/pt/pid`"

echo 'Running naming test'
bin/gdi.sh tests/naming/cmd.txt

Expand Down

0 comments on commit 2572745

Please sign in to comment.