Skip to content

Commit

Permalink
Merge pull request #52 from at88mph/bash-scriptable-urls
Browse files Browse the repository at this point in the history
Bash scriptable urls
  • Loading branch information
at88mph authored Mar 28, 2023
2 parents ae5b364 + 8c801ad commit 2c0a3ce
Show file tree
Hide file tree
Showing 19 changed files with 1,069 additions and 584 deletions.
2 changes: 1 addition & 1 deletion cadc-download-manager-server/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ repositories {
mavenLocal()
}

version = '1.4.5'
version = '1.5.0'
group = 'org.opencadc'
sourceCompatibility = 1.8

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,18 +73,15 @@
import ca.nrc.cadc.auth.AuthenticationUtil;
import ca.nrc.cadc.dlm.DownloadRequest;
import ca.nrc.cadc.dlm.DownloadTuple;
import ca.nrc.cadc.dlm.DownloadUtil;
import ca.nrc.cadc.log.ServletLogInfo;
import java.io.IOException;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.security.auth.Subject;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
Expand Down Expand Up @@ -112,12 +109,11 @@ public class DispatcherServlet extends HttpServlet {
private static final long serialVersionUID = 202008040800L;

private static final Logger log = Logger.getLogger(DispatcherServlet.class);
private static int ONE_YEAR = 365 * 24 * 3600;

public static String INTERNAL_FORWARD_PARAMETER = "downloadRequest";
public static String URLS = "URL List";
public static String HTMLLIST = "HTML List";
public static String WEBSTART = "Java Webstart";
public static String SHELL_SCRIPT = "Shell Script";


/// Used during JSP compilation
Expand All @@ -128,88 +124,30 @@ public class DispatcherServlet extends HttpServlet {
* to save setting for future use.
*
* @param request The HTTP Request.
* @param response The HTTP Response.
* @return name of page to forward to, null if caller should offer choices to user
*/
public static String getDownloadMethod(HttpServletRequest request, HttpServletResponse response) {
public static String getDownloadMethod(HttpServletRequest request) {
String method = request.getParameter(DLMInputHandler.PARAM_METHOD);
Cookie ck = null;

// get cookie
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals("DownloadMethod")) {
ck = cookie;
}
}
}
final String target;

String target = null;
if ((method == null) && (ck != null) && (ck.getValue() != null)) {
method = ck.getValue();
if ((URLS.equals(method) || WEBSTART.equals(method))
&& (request.getParameter("execute") == null)) {
target = "/clearChoice.jsp";
if (URLS.equals(method)) {
request.setAttribute("Description",
"urlListDescription.html");
} else {
request.setAttribute("Description",
"javaWebStartDescription.html");
}
if (method != null) {
if (URLS.equals(method)) {
target = UrlListServlet.FILE_LIST_TARGET;
} else if (WEBSTART.equals(method)) {
target = "/javaWebstart";
} else if (HTMLLIST.equals(method)) {
target = "/wget.jsp";
}
}

if (target == null) {
if (method != null) {
if (URLS.equals(method)) {
target = UrlListServlet.FILE_LIST_TARGET;
} else if (WEBSTART.equals(method)) {
target = "/javaWebstart";
} else if (HTMLLIST.equals(method)) {
target = "/wget.jsp";
} else {
return null;
}
} else if (SHELL_SCRIPT.equals(method)) {
target = ShellScriptServlet.SCRIPT_TARGET;
} else {
// invalid method, tell page we did not forward
if (ck != null) {
// delete cookie on client
ck.setValue(null);
ck.setMaxAge(0); // delete
response.addCookie(ck);
}
return null;
}
}
log.debug("Determined method: " + method);

if (request.getParameter("remember") != null) {
// set/edit cookie
if (ck == null) { // new
ck = new Cookie("DownloadMethod", method);
ck.setPath(request.getContextPath());
ck.setMaxAge(ONE_YEAR);
response.addCookie(ck);
} else if (!method.equals(ck.getValue())) { // changed
ck.setValue(method);
ck.setPath(request.getContextPath());
ck.setMaxAge(ONE_YEAR);
response.addCookie(ck);
}
} else {
if ((request.getParameter("clearCookie") != null)
&& (ck != null)) {
// remove cookie
log.debug("Delete cookie!!!");
ck.setPath(request.getContextPath());
ck.setMaxAge(0);
response.addCookie(ck);
}
// invalid method, tell page we did not forward
return null;
}

log.debug("Determined method: " + method);
return target;
}

Expand Down Expand Up @@ -301,7 +239,7 @@ public Object run() throws Exception {
}

// check for preferred/selected download method
String target = getDownloadMethod(request, response);
String target = getDownloadMethod(request);
log.debug("Target: " + target);
if (target == null) {
target = "/chooser.jsp";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
/*
************************************************************************
******************* CANADIAN ASTRONOMY DATA CENTRE *******************
************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES **************
*
* (c) 2023. (c) 2023.
* Government of Canada Gouvernement du Canada
* National Research Council Conseil national de recherches
* Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6
* All rights reserved Tous droits réservés
*
* NRC disclaims any warranties, Le CNRC dénie toute garantie
* expressed, implied, or énoncée, implicite ou légale,
* statutory, of any kind with de quelque nature que ce
* respect to the software, soit, concernant le logiciel,
* including without limitation y compris sans restriction
* any warranty of merchantability toute garantie de valeur
* or fitness for a particular marchande ou de pertinence
* purpose. NRC shall not be pour un usage particulier.
* liable in any event for any Le CNRC ne pourra en aucun cas
* damages, whether direct or être tenu responsable de tout
* indirect, special or general, dommage, direct ou indirect,
* consequential or incidental, particulier ou général,
* arising from the use of the accessoire ou fortuit, résultant
* software. Neither the name de l'utilisation du logiciel. Ni
* of the National Research le nom du Conseil National de
* Council of Canada nor the Recherches du Canada ni les noms
* names of its contributors may de ses participants ne peuvent
* be used to endorse or promote être utilisés pour approuver ou
* products derived from this promouvoir les produits dérivés
* software without specific prior de ce logiciel sans autorisation
* written permission. préalable et particulière
* par écrit.
*
* This file is part of the Ce fichier fait partie du projet
* OpenCADC project. OpenCADC.
*
* OpenCADC is free software: OpenCADC est un logiciel libre ;
* you can redistribute it and/or vous pouvez le redistribuer ou le
* modify it under the terms of modifier suivant les termes de
* the GNU Affero General Public la “GNU Affero General Public
* License as published by the License” telle que publiée
* Free Software Foundation, par la Free Software Foundation
* either version 3 of the : soit la version 3 de cette
* License, or (at your option) licence, soit (à votre gré)
* any later version. toute version ultérieure.
*
* OpenCADC is distributed in the OpenCADC est distribué
* hope that it will be useful, dans l’espoir qu’il vous
* but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE
* without even the implied GARANTIE : sans même la garantie
* warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ
* or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF
* PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence
* General Public License for Générale Publique GNU Affero
* more details. pour plus de détails.
*
* You should have received Vous devriez avoir reçu une
* a copy of the GNU Affero copie de la Licence Générale
* General Public License along Publique GNU Affero avec
* with OpenCADC. If not, see OpenCADC ; si ce n’est
* <http://www.gnu.org/licenses/>. pas le cas, consultez :
* <http://www.gnu.org/licenses/>.
*
*
************************************************************************
*/

package ca.nrc.cadc.dlm.server;

import ca.nrc.cadc.date.DateUtil;
import ca.nrc.cadc.dlm.DownloadDescriptor;
import ca.nrc.cadc.util.FileUtil;
import ca.nrc.cadc.util.StringUtil;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.Writer;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;


/**
* Generate a Bash script with the Download URLs.
*/
class ScriptGenerator {
private static final String NEWLINE = "\n";
private static final String AUTH_SCRIPT_TEMPLATE_FILENAME = "cadc-download-auth-template.sh";
private static final String ANON_SCRIPT_TEMPLATE_FILENAME = "cadc-download-anon-template.sh";
private static final String VARIABLE_REPLACE = "%%%";
private static final String VARIABLE_EXPIRY_REPLACE =
ScriptGenerator.VARIABLE_REPLACE + "EXPIRY" + ScriptGenerator.VARIABLE_REPLACE;
private static final String VARIABLE_TOKEN_REPLACE =
ScriptGenerator.VARIABLE_REPLACE + "TOKEN" + ScriptGenerator.VARIABLE_REPLACE;
private static final String VARIABLE_URLS_REPLACE =
ScriptGenerator.VARIABLE_REPLACE + "URLS" + ScriptGenerator.VARIABLE_REPLACE;

private static final String VARIABLE_ERROR_URIS_REPLACE =
ScriptGenerator.VARIABLE_REPLACE + "ERRORURIS" + ScriptGenerator.VARIABLE_REPLACE;
private static final String ERROR_URI_MESSAGE_DELIMINATOR = "|||";

private final Iterator<DownloadDescriptor> downloadDescriptors;
private final String authToken;
private final Date expiryDate;


ScriptGenerator(final Iterator<DownloadDescriptor> downloadDescriptors) {
this(downloadDescriptors, null, null);
}

ScriptGenerator(final Iterator<DownloadDescriptor> downloadDescriptors, final String authToken,
final Date expiryDate) {
this.downloadDescriptors = downloadDescriptors;
this.authToken = authToken;
this.expiryDate = expiryDate;

// If the auth token was provided, the expiry date should be provided as well.
if (this.expiryDate == null && StringUtil.hasLength(this.authToken)) {
throw new IllegalArgumentException("The Expiry Date is required when the token is supplied.");
} else if (this.downloadDescriptors == null || !this.downloadDescriptors.hasNext()) {
throw new IllegalArgumentException("The DownloadDescriptor iterator is required.");
}
}

/**
* Determine the appropriate template script file, and write out the string template variable values.
* @param writer The Writer to send data to.
* @throws IOException If any I/O problems occur.
*/
void generate(final Writer writer) throws IOException {
final String templateFile = StringUtil.hasLength(this.authToken)
? ScriptGenerator.AUTH_SCRIPT_TEMPLATE_FILENAME
: ScriptGenerator.ANON_SCRIPT_TEMPLATE_FILENAME;
final URL templateFileURL = FileUtil.getURLFromResource(templateFile, ScriptGenerator.class);
try (final InputStream inputStream = templateFileURL.openStream()) {
final Reader inputStreamReader = new InputStreamReader(inputStream);
final BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
final List<DownloadDescriptor> errorDownloadDescriptors = new ArrayList<>();
final List<DownloadDescriptor> successDownloadDescriptors = new ArrayList<>();

// Separate the successful Downloads from the errors.
this.downloadDescriptors.forEachRemaining(downloadDescriptor -> {
if (downloadDescriptor.url == null) {
errorDownloadDescriptors.add(downloadDescriptor);
} else {
successDownloadDescriptors.add(downloadDescriptor);
}
});

String line;
while ((line = bufferedReader.readLine()) != null) {
if (line.contains(ScriptGenerator.VARIABLE_REPLACE)) {
if (line.contains(ScriptGenerator.VARIABLE_EXPIRY_REPLACE)) {
writer.write(line.replace(ScriptGenerator.VARIABLE_EXPIRY_REPLACE,
DateUtil.getDateFormat(DateUtil.ISO8601_DATE_FORMAT_LOCAL, DateUtil.UTC)
.format(this.expiryDate)));
} else if (line.contains(ScriptGenerator.VARIABLE_TOKEN_REPLACE)) {
writer.write(line.replace(ScriptGenerator.VARIABLE_TOKEN_REPLACE, this.authToken));
} else if (line.contains(ScriptGenerator.VARIABLE_URLS_REPLACE)) {
for (final Iterator<DownloadDescriptor> downloadDescriptorIterator
= successDownloadDescriptors.iterator(); downloadDescriptorIterator.hasNext(); ) {
final DownloadDescriptor downloadDescriptor = downloadDescriptorIterator.next();
writer.write("\"" + downloadDescriptor.url + "\"");
if (downloadDescriptorIterator.hasNext()) {
writer.write(ScriptGenerator.NEWLINE);
}
}
} else if (line.contains(ScriptGenerator.VARIABLE_ERROR_URIS_REPLACE)) {
// Error URIs are written as the URI|||Error Message.
for (final Iterator<DownloadDescriptor> downloadDescriptorIterator
= errorDownloadDescriptors.iterator(); downloadDescriptorIterator.hasNext(); ) {
final DownloadDescriptor downloadDescriptor = downloadDescriptorIterator.next();
writer.write("\"" + downloadDescriptor.uri + ScriptGenerator.ERROR_URI_MESSAGE_DELIMINATOR
+ downloadDescriptor.error + "\"");
if (downloadDescriptorIterator.hasNext()) {
writer.write(ScriptGenerator.NEWLINE);
}
}
}
writer.write(ScriptGenerator.NEWLINE);
} else {
writer.write(line);
writer.write(ScriptGenerator.NEWLINE);
}
}
}
}
}
Loading

0 comments on commit 2c0a3ce

Please sign in to comment.