Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.tsugi.json.IMSJSONRequest Maven / Gradle / Ivy
package org.tsugi.json;
import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URLDecoder;
import java.security.MessageDigest;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import net.oauth.OAuthAccessor;
import net.oauth.OAuthConsumer;
import net.oauth.OAuthMessage;
import net.oauth.OAuthValidator;
import net.oauth.SimpleOAuthValidator;
import net.oauth.server.OAuthServlet;
import net.oauth.signature.OAuthSignatureMethod;
import org.tsugi.basiclti.Base64;
import org.json.simple.JSONValue;
@Slf4j
public class IMSJSONRequest {
public final static String STATUS = "status";
public final static String STATUS_CODE = "code";
public final static String STATUS_DESCRIPTION = "description";
public final static String CODE_MAJOR_SUCCESS = "success";
public final static String CODE_MAJOR_FAILURE = "failure";
public final static String CODE_MAJOR_UNSUPPORTED = "unsupported";
public String postBody = null;
private String header = null;
private String oauth_body_hash = null;
private String oauth_consumer_key = null;
private String oauth_signature_method = null;
public boolean valid = false;
public String errorMessage = null;
public String base_string = null;
private static final String APPLICATION_JSON = "application/json";
public String getOAuthConsumerKey()
{
return oauth_consumer_key;
}
public String getPostBody()
{
return postBody;
}
// Normal Constructor
public IMSJSONRequest(String oauth_consumer_key, String oauth_secret, HttpServletRequest request)
{
loadFromRequest(request);
if ( ! valid ) return;
validateRequest(oauth_consumer_key, oauth_secret, request);
}
// Constructor for delayed validation
public IMSJSONRequest(HttpServletRequest request)
{
loadFromRequest(request);
}
// Constructor for testing...
public IMSJSONRequest(String bodyString)
{
postBody = bodyString;
}
// Load but do not check the authentication
@SuppressWarnings("deprecation")
public void loadFromRequest(HttpServletRequest request)
{
header = request.getHeader("Authorization");
log.debug("Header: {}", header);
oauth_body_hash = null;
oauth_signature_method = null;
if ( header != null ) {
if (header.startsWith("OAuth ")) header = header.substring(5);
String [] parms = header.split(",");
for ( String parm : parms ) {
parm = parm.trim();
if ( parm.startsWith("oauth_body_hash=") ) {
String [] pieces = parm.split("\"");
if ( pieces.length == 2 ) oauth_body_hash = URLDecoder.decode(pieces[1]);
}
if ( parm.startsWith("oauth_signature_method=") ) {
String [] pieces = parm.split("\"");
if ( pieces.length == 2 ) oauth_signature_method = URLDecoder.decode(pieces[1]);
}
if ( parm.startsWith("oauth_consumer_key=") ) {
String [] pieces = parm.split("\"");
if ( pieces.length == 2 ) oauth_consumer_key = URLDecoder.decode(pieces[1]);
}
}
}
if ( oauth_body_hash == null ) {
errorMessage = "Did not find oauth_body_hash";
log.info("{}\n{}", errorMessage, header);
return;
}
log.debug("OBH={}", oauth_body_hash);
byte[] buf = new byte[1024];
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int chars = 0;
try {
ServletInputStream is = request.getInputStream();
int readNum;
do {
readNum = is.read(buf);
if (readNum>0) {
bos.write(buf, 0, readNum);
chars = chars + readNum;
// We dont' want a DOS - Also helps w.r.t. SHA1
if ( chars > 10000000 ) {
errorMessage = "Message body size exceeded";
return;
}
}
} while (readNum>=0);
} catch(Exception e) {
errorMessage = "Could not read message body:"+e.getMessage();
return;
}
byte[] bytes = bos.toByteArray();
try {
postBody = new String(bytes, "UTF-8");
MessageDigest md = null;
if ( "HMAC-SHA256".equalsIgnoreCase(oauth_signature_method) ) {
md = MessageDigest.getInstance("SHA-256");
} else {
md = MessageDigest.getInstance("SHA-1");
}
md.update(bytes);
byte[] output = Base64.encode(md.digest());
String hash = new String(output);
log.debug("HASH={} bytes={}", hash, bytes.length);
if ( ! hash.equals(oauth_body_hash) ) {
errorMessage = "Body hash does not match. bytes="+bytes.length;
if ( oauth_signature_method != null ) errorMessage += " oauth_signature_method="+oauth_signature_method;
log.debug(postBody);
return;
}
} catch (Exception e) {
errorMessage = "Could not compute body hash. bytes="+bytes.length;
if ( oauth_signature_method != null ) errorMessage += " oauth_signature_method="+oauth_signature_method;
errorMessage += " Exception:" + e.getMessage();
return;
}
valid = true; // So far we are valid
}
// Assumes data is all loaded
public void validateRequest(String oauth_consumer_key, String oauth_secret, HttpServletRequest request)
{
validateRequest(oauth_consumer_key, oauth_secret, request, null) ;
}
public void validateRequest(String oauth_consumer_key, String oauth_secret, HttpServletRequest request, String URL)
{
valid = false;
OAuthMessage oam = OAuthServlet.getMessage(request, URL);
OAuthValidator oav = new SimpleOAuthValidator();
OAuthConsumer cons = new OAuthConsumer("about:blank#OAuth+CallBack+NotUsed",
oauth_consumer_key, oauth_secret, null);
OAuthAccessor acc = new OAuthAccessor(cons);
try {
base_string = OAuthSignatureMethod.getBaseString(oam);
} catch (Exception e) {
base_string = null;
}
try {
oav.validateMessage(oam,acc);
} catch(Exception e) {
errorMessage = "Launch fails OAuth validation: "+e.getMessage();
return;
}
valid = true;
}
public boolean inArray(final String [] theArray, final String theString)
{
if ( theString == null ) return false;
for ( String str : theArray ) {
if ( theString.equals(str) ) return true;
}
return false;
}
public static Map getStatusUnsupported(String desc)
{
return getStatus(desc, CODE_MAJOR_UNSUPPORTED);
}
public static Map getStatusFailure(String desc)
{
return getStatus(desc, CODE_MAJOR_FAILURE);
}
public static Map getStatusSuccess(String desc)
{
return getStatus(desc, CODE_MAJOR_SUCCESS);
}
public static Map getStatus(String description, String major)
{
Map retval = new LinkedHashMap();
retval.put(STATUS_CODE,major);
retval.put(STATUS_DESCRIPTION,description);
return retval;
}
/* IMS JSON version of Errors - does the complete request - returns the JSON in case
the code above us wants to log it. */
@SuppressWarnings("static-access")
public static String doErrorJSON(HttpServletRequest request,HttpServletResponse response,
IMSJSONRequest json, String message, Exception e)
throws java.io.IOException
{
response.setContentType(APPLICATION_JSON);
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
Map jsonResponse = new TreeMap();
Map status = null;
if ( json == null ) {
status = IMSJSONRequest.getStatusFailure(message);
} else {
status = json.getStatusFailure(message);
if ( json.base_string != null ) {
jsonResponse.put("base_string", json.base_string);
}
if ( json.errorMessage != null ) {
jsonResponse.put("error_message", json.errorMessage);
}
}
jsonResponse.put(IMSJSONRequest.STATUS, status);
if ( e != null ) {
jsonResponse.put("exception", e.getLocalizedMessage());
try {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw, true);
log.error("{}", pw);
pw.flush();
sw.flush();
jsonResponse.put("traceback", sw.toString() );
} catch ( Exception f ) {
jsonResponse.put("traceback", f.getLocalizedMessage());
}
}
String jsonText = JSONValue.toJSONString(jsonResponse);
PrintWriter out = response.getWriter();
out.println(jsonText);
return jsonText;
}
/** Unit Tests */
static final String inputTestData = "\n" +
"\n" +
"\n" +
"\n" +
"V1.0 \n" +
"999999123 \n" +
" \n" +
" \n" +
"\n" +
"\n" +
"\n" +
"\n" +
"3124567 \n" +
" \n" +
"\n" +
"\n" +
"en-us \n" +
"A \n" +
" \n" +
" \n" +
" \n" +
" \n" +
" \n" +
" ";
public static void runTest() {
/*
log.debug("Runnig test.");
IMSJSONRequest pox = new IMSJSONRequest(inputTestData);
log.debug("Version = {}", pox.getHeaderVersion());
log.debug("Operation = {}", pox.getOperation());
Map bodyMap = pox.getBodyMap();
String guid = bodyMap.get("/resultRecord/sourcedGUID/sourcedId");
log.debug("guid={}", guid);
String grade = bodyMap.get("/resultRecord/result/resultScore/textString");
log.debug("grade={}", grade);
String desc = "Message received and validated operation="+pox.getOperation()+
" guid="+guid+" grade="+grade;
String output = pox.getResponseUnsupported(desc);
log.debug("---- Unsupported ----");
log.debug(output);
Properties props = new Properties();
props.setProperty("fred","zap");
props.setProperty("sam",IMSPOXRequest.MINOR_IDALLOC);
log.debug("---- Generate logger Error ----");
output = pox.getResponseFailure(desc,props);
log.debug("---- Failure ----");
log.debug(output);
Map theMap = new TreeMap ();
theMap.put("/readMembershipResponse/membershipRecord/sourcedId", "123course456");
List> lm = new ArrayList>();
Map mm = new TreeMap();
mm.put("/personSourcedId","123user456");
mm.put("/role/roleType","Learner");
lm.add(mm);
mm = new TreeMap();
mm.put("/personSourcedId","789user123");
mm.put("/role/roleType","Instructor");
lm.add(mm);
theMap.put("/readMembershipResponse/membershipRecord/membership/member", lm);
String theXml = XMLMap.getXMLFragment(theMap, true);
log.debug("th={}", theXml);
output = pox.getResponseSuccess(desc,theXml);
log.debug("---- Success String ----");
log.debug(output);
*/
}
/*
roleType:
Learner
Instructor
ContentDeveloper
Member
Manager
Mentor
Administrator
TeachingAssistant
fieldType:
Boolean
Integer
Real
String
GUID.TYPE
GUID.TYPE
MEMBERSHIPIDTYPE.TYPE
GUID.TYPE
STRING
STRING
DATETIME
DATETIME
BOOLEAN
LANGUAGESET.TYPE
STRING
STATUS.TYPE
DATETIME
GUID.TYPE
STRING
FIELDTYPE.TYPE
STRING
STRING
FIELDTYPE.TYPE
STRING
INTEGER
GUID.TYPE
*/
}