Further cleanups. Still missing:
- All tests extend TestCase, should use annotations instead - Several elements throw Exception - Key Fetchers should use RESTTemplates and be in a separate utility setpull/105/merge
parent
b86abdd761
commit
fe3bbfb3d5
|
@ -388,7 +388,7 @@ public class AbstractOIDCAuthenticationFilter extends
|
||||||
*/
|
*/
|
||||||
protected Authentication handleAuthorizationGrantResponse(
|
protected Authentication handleAuthorizationGrantResponse(
|
||||||
String authorizationGrant, HttpServletRequest request,
|
String authorizationGrant, HttpServletRequest request,
|
||||||
OIDCServerConfiguration serverConfig) throws Exception {
|
OIDCServerConfiguration serverConfig) {
|
||||||
|
|
||||||
final boolean debug = logger.isDebugEnabled();
|
final boolean debug = logger.isDebugEnabled();
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,8 @@ public class OIDCServerConfiguration {
|
||||||
|
|
||||||
private String jwkSigningUrl;
|
private String jwkSigningUrl;
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: these keys should be settable through other means beyond discovery
|
||||||
private Key encryptKey;
|
private Key encryptKey;
|
||||||
|
|
||||||
private Key signingKey;
|
private Key signingKey;
|
||||||
|
@ -124,6 +126,7 @@ public class OIDCServerConfiguration {
|
||||||
this.jwkSigningUrl = jwkSigningUrl;
|
this.jwkSigningUrl = jwkSigningUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: this should not throw Exception
|
||||||
public Key getSigningKey() throws Exception {
|
public Key getSigningKey() throws Exception {
|
||||||
if(signingKey == null){
|
if(signingKey == null){
|
||||||
if(x509SigningUrl != null){
|
if(x509SigningUrl != null){
|
||||||
|
@ -140,6 +143,7 @@ public class OIDCServerConfiguration {
|
||||||
return signingKey;
|
return signingKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: this should not throw Exception
|
||||||
public Key getEncryptionKey() throws Exception {
|
public Key getEncryptionKey() throws Exception {
|
||||||
if(encryptKey == null){
|
if(encryptKey == null){
|
||||||
if(x509EncryptUrl != null){
|
if(x509EncryptUrl != null){
|
||||||
|
@ -156,6 +160,7 @@ public class OIDCServerConfiguration {
|
||||||
return encryptKey;
|
return encryptKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: this should not throw exception
|
||||||
public void checkKeys() throws Exception {
|
public void checkKeys() throws Exception {
|
||||||
encryptKey = null;
|
encryptKey = null;
|
||||||
signingKey = null;
|
signingKey = null;
|
||||||
|
@ -176,6 +181,7 @@ public class OIDCServerConfiguration {
|
||||||
+ jwkSigningUrl + "]";
|
+ jwkSigningUrl + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: what is this function for? nobody uses it, and it seems backwards for construction
|
||||||
public DynamicJwtSigningAndValidationService getDynamic() throws Exception{
|
public DynamicJwtSigningAndValidationService getDynamic() throws Exception{
|
||||||
dynamic = new DynamicJwtSigningAndValidationService(getX509SigningUrl(), getJwkSigningUrl(), getClientSecret());
|
dynamic = new DynamicJwtSigningAndValidationService(getX509SigningUrl(), getJwkSigningUrl(), getClientSecret());
|
||||||
return dynamic;
|
return dynamic;
|
||||||
|
|
|
@ -11,6 +11,10 @@ import org.springframework.security.core.userdetails.UserDetails;
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: what is this class for?
|
||||||
|
|
||||||
|
|
||||||
public class OIDCUserDetailService implements UserDetailsService,
|
public class OIDCUserDetailService implements UserDetailsService,
|
||||||
AuthenticationUserDetailsService<OpenIdConnectAuthenticationToken> {
|
AuthenticationUserDetailsService<OpenIdConnectAuthenticationToken> {
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@ import org.springframework.validation.Errors;
|
||||||
import org.springframework.validation.ValidationUtils;
|
import org.springframework.validation.ValidationUtils;
|
||||||
import org.springframework.validation.Validator;
|
import org.springframework.validation.Validator;
|
||||||
|
|
||||||
|
// TODO: is this used anywhere?
|
||||||
|
|
||||||
public class UrlValidator implements Validator{
|
public class UrlValidator implements Validator{
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,14 +21,17 @@ public class UrlValidator implements Validator{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO this isn't called anywhere
|
||||||
public void validate1(Object obj, Errors e) {
|
public void validate1(Object obj, Errors e) {
|
||||||
ValidationUtils.rejectIfEmpty(e, "x509SigningUrl", "x509SigningUrl.empty");
|
ValidationUtils.rejectIfEmpty(e, "x509SigningUrl", "x509SigningUrl.empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO this isn't called anywhere
|
||||||
public void validate2(Object obj, Errors e) {
|
public void validate2(Object obj, Errors e) {
|
||||||
ValidationUtils.rejectIfEmpty(e, "jwkEncryptUrl", "jwkEncryptUrl.empty");
|
ValidationUtils.rejectIfEmpty(e, "jwkEncryptUrl", "jwkEncryptUrl.empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO this isn't called anywhere
|
||||||
public void validate3(Object obj, Errors e) {
|
public void validate3(Object obj, Errors e) {
|
||||||
ValidationUtils.rejectIfEmpty(e, "jwkSigningUrl", "jwkSigningUrl.empty");
|
ValidationUtils.rejectIfEmpty(e, "jwkSigningUrl", "jwkSigningUrl.empty");
|
||||||
}
|
}
|
||||||
|
|
|
@ -173,6 +173,7 @@ public class HmacSigner extends AbstractJwtSigner implements InitializingBean {
|
||||||
this.passphrase = passphrase;
|
this.passphrase = passphrase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: this this indirection to a lazy constructor necessary?
|
||||||
private Mac getMac() throws NoSuchAlgorithmException {
|
private Mac getMac() throws NoSuchAlgorithmException {
|
||||||
if(mac == null){
|
if(mac == null){
|
||||||
mac = Mac.getInstance(JwsAlgorithm.getByName(super.getAlgorithm())
|
mac = Mac.getInstance(JwsAlgorithm.getByName(super.getAlgorithm())
|
||||||
|
|
|
@ -138,7 +138,7 @@ public class RsaSigner extends AbstractJwtSigner implements InitializingBean {
|
||||||
* org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
* org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void afterPropertiesSet() throws Exception {
|
public void afterPropertiesSet() throws NoSuchAlgorithmException, GeneralSecurityException {
|
||||||
|
|
||||||
// unsupported algorithm will throw a NoSuchAlgorithmException
|
// unsupported algorithm will throw a NoSuchAlgorithmException
|
||||||
signer = Signature.getInstance(JwsAlgorithm.getByName(super.getAlgorithm()).getStandardName()); // ,PROVIDER);
|
signer = Signature.getInstance(JwsAlgorithm.getByName(super.getAlgorithm()).getStandardName()); // ,PROVIDER);
|
||||||
|
@ -230,7 +230,8 @@ public class RsaSigner extends AbstractJwtSigner implements InitializingBean {
|
||||||
public void setPrivateKey(RSAPrivateKey privateKey) {
|
public void setPrivateKey(RSAPrivateKey privateKey) {
|
||||||
this.privateKey = privateKey;
|
this.privateKey = privateKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: this this indirection to a lazy constructor really necessary?
|
||||||
private Signature getSigner() throws NoSuchAlgorithmException{
|
private Signature getSigner() throws NoSuchAlgorithmException{
|
||||||
if(signer == null){
|
if(signer == null){
|
||||||
signer = Signature.getInstance(JwsAlgorithm.getByName(super.getAlgorithm()).getStandardName());
|
signer = Signature.getInstance(JwsAlgorithm.getByName(super.getAlgorithm()).getStandardName());
|
||||||
|
|
|
@ -71,8 +71,6 @@ public interface JwtSigningAndValidationService {
|
||||||
* @return the signed jwt
|
* @return the signed jwt
|
||||||
* @throws NoSuchAlgorithmException
|
* @throws NoSuchAlgorithmException
|
||||||
*/
|
*/
|
||||||
public boolean validateIssuedAt(Jwt jwt);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks to see when this JWT was issued
|
* Checks to see when this JWT was issued
|
||||||
*
|
*
|
||||||
|
@ -81,7 +79,7 @@ public interface JwtSigningAndValidationService {
|
||||||
* @return true if the issued at is valid, false if not
|
* @return true if the issued at is valid, false if not
|
||||||
* @throws NoSuchAlgorithmException
|
* @throws NoSuchAlgorithmException
|
||||||
*/
|
*/
|
||||||
public boolean validateAudience(Jwt jwt, String clientId);
|
public boolean validateIssuedAt(Jwt jwt);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks the audience that the given JWT against the client_id of the Client
|
* Checks the audience that the given JWT against the client_id of the Client
|
||||||
|
@ -92,7 +90,7 @@ public interface JwtSigningAndValidationService {
|
||||||
* @return true if the audience matches the clinet_id, false if otherwise
|
* @return true if the audience matches the clinet_id, false if otherwise
|
||||||
* @throws NoSuchAlgorithmException
|
* @throws NoSuchAlgorithmException
|
||||||
*/
|
*/
|
||||||
public boolean validateNonce(Jwt jwt, String nonce);
|
public boolean validateAudience(Jwt jwt, String clientId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks to see if the nonce parameter sent in the Authorization Request
|
* Checks to see if the nonce parameter sent in the Authorization Request
|
||||||
|
@ -104,7 +102,7 @@ public interface JwtSigningAndValidationService {
|
||||||
* @return true if both nonce parameters are equal, false if otherwise
|
* @return true if both nonce parameters are equal, false if otherwise
|
||||||
* @throws NoSuchAlgorithmException
|
* @throws NoSuchAlgorithmException
|
||||||
*/
|
*/
|
||||||
public void signJwt(Jwt jwt) throws NoSuchAlgorithmException;
|
public boolean validateNonce(Jwt jwt, String nonce);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sign a jwt using the selected algorithm. The algorithm is selected using the String parameter values specified
|
* Sign a jwt using the selected algorithm. The algorithm is selected using the String parameter values specified
|
||||||
|
@ -114,6 +112,8 @@ public interface JwtSigningAndValidationService {
|
||||||
* @param alg the name of the algorithm to use, as specified in JWS s.6
|
* @param alg the name of the algorithm to use, as specified in JWS s.6
|
||||||
* @return the signed jwt
|
* @return the signed jwt
|
||||||
*/
|
*/
|
||||||
|
public void signJwt(Jwt jwt) throws NoSuchAlgorithmException;
|
||||||
|
|
||||||
//TODO: implement later; only need signJwt(Jwt jwt) for now
|
//TODO: implement later; only need signJwt(Jwt jwt) for now
|
||||||
//public Jwt signJwt(Jwt jwt, String alg);
|
//public Jwt signJwt(Jwt jwt, String alg);
|
||||||
|
|
||||||
|
|
|
@ -22,11 +22,11 @@ public abstract class AbstractJwtSigningAndValidationService implements JwtSigni
|
||||||
|
|
||||||
Date expiration = jwt.getClaims().getExpiration();
|
Date expiration = jwt.getClaims().getExpiration();
|
||||||
|
|
||||||
if (expiration != null)
|
if (expiration != null) {
|
||||||
return new Date().after(expiration);
|
return new Date().after(expiration);
|
||||||
else
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -34,8 +34,9 @@ public abstract class AbstractJwtSigningAndValidationService implements JwtSigni
|
||||||
|
|
||||||
String iss = jwt.getClaims().getIssuer();
|
String iss = jwt.getClaims().getIssuer();
|
||||||
|
|
||||||
if (iss.equals(expectedIssuer))
|
if (iss.equals(expectedIssuer)) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -44,10 +45,10 @@ public abstract class AbstractJwtSigningAndValidationService implements JwtSigni
|
||||||
public boolean validateSignature(String jwtString) throws NoSuchAlgorithmException {
|
public boolean validateSignature(String jwtString) throws NoSuchAlgorithmException {
|
||||||
|
|
||||||
for (JwtSigner signer : getSigners().values()) {
|
for (JwtSigner signer : getSigners().values()) {
|
||||||
if (signer.verify(jwtString))
|
if (signer.verify(jwtString)) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,19 +56,19 @@ public abstract class AbstractJwtSigningAndValidationService implements JwtSigni
|
||||||
public boolean validateIssuedAt(Jwt jwt) {
|
public boolean validateIssuedAt(Jwt jwt) {
|
||||||
Date issuedAt = jwt.getClaims().getIssuedAt();
|
Date issuedAt = jwt.getClaims().getIssuedAt();
|
||||||
|
|
||||||
if (issuedAt != null)
|
if (issuedAt != null) {
|
||||||
return new Date().before(issuedAt);
|
return new Date().before(issuedAt);
|
||||||
else
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean validateAudience(Jwt jwt, String clientId) {
|
public boolean validateAudience(Jwt jwt, String expectedAudience) {
|
||||||
|
|
||||||
if(jwt.getClaims().getAudience().equals(clientId)){
|
if(jwt.getClaims().getAudience().equals(expectedAudience)){
|
||||||
return true;
|
return true;
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,8 +77,7 @@ public abstract class AbstractJwtSigningAndValidationService implements JwtSigni
|
||||||
public boolean validateNonce(Jwt jwt, String nonce) {
|
public boolean validateNonce(Jwt jwt, String nonce) {
|
||||||
if(jwt.getClaims().getNonce().equals(nonce)){
|
if(jwt.getClaims().getNonce().equals(nonce)){
|
||||||
return true;
|
return true;
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,12 +34,13 @@ public class DynamicJwtSigningAndValidationService extends AbstractJwtSigningAnd
|
||||||
|
|
||||||
private Map<String, ? extends JwtSigner> signers;
|
private Map<String, ? extends JwtSigner> signers;
|
||||||
|
|
||||||
public DynamicJwtSigningAndValidationService(String x509SigningUrl, String jwkSigningUrl, String clientSecret) throws Exception {
|
public DynamicJwtSigningAndValidationService(String x509SigningUrl, String jwkSigningUrl, String clientSecret) {
|
||||||
setX509SigningUrl(x509SigningUrl);
|
setX509SigningUrl(x509SigningUrl);
|
||||||
setJwkSigningUrl(jwkSigningUrl);
|
setJwkSigningUrl(jwkSigningUrl);
|
||||||
setClientSecret(clientSecret);
|
setClientSecret(clientSecret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: this function should not throw Exception
|
||||||
public Key getSigningKey() throws Exception {
|
public Key getSigningKey() throws Exception {
|
||||||
if(signingKey == null){
|
if(signingKey == null){
|
||||||
if(x509SigningUrl != null){
|
if(x509SigningUrl != null){
|
||||||
|
@ -118,24 +119,27 @@ public class DynamicJwtSigningAndValidationService extends AbstractJwtSigningAnd
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public JwtSigner getSigner(String str) throws Exception {
|
public JwtSigner getSigner(String str) {
|
||||||
JwtHeader header = Jwt.parse(str).getHeader();
|
JwtHeader header = Jwt.parse(str).getHeader();
|
||||||
String alg = header.getAlgorithm();
|
String alg = header.getAlgorithm();
|
||||||
JwtSigner signer = null;
|
JwtSigner signer = null;
|
||||||
|
|
||||||
if(alg.equals("HS256") || alg.equals("HS384") || alg.equals("HS512")){
|
if(alg.equals("HS256") || alg.equals("HS384") || alg.equals("HS512")){
|
||||||
signer = new HmacSigner(alg, clientSecret); // TODO: huh? no, we're not signing with the client secret
|
signer = new HmacSigner(alg, clientSecret); // TODO: huh? no, we're not signing with the client secret
|
||||||
}
|
} else if (alg.equals("RS256") || alg.equals("RS384") || alg.equals("RS512")){
|
||||||
|
|
||||||
else if (alg.equals("RS256") || alg.equals("RS384") || alg.equals("RS512")){
|
PublicKey rsaSigningKey = null;
|
||||||
signer = new RsaSigner(alg, (PublicKey) getSigningKey(), null);
|
try {
|
||||||
}
|
rsaSigningKey = (PublicKey) getSigningKey();
|
||||||
|
} catch (Exception e) {
|
||||||
else if (alg.equals("none")){
|
// FIXME this function call should not throw Exception
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
signer = new RsaSigner(alg, rsaSigningKey, null);
|
||||||
|
} else if (alg.equals("none")){
|
||||||
signer = new PlaintextSigner();
|
signer = new PlaintextSigner();
|
||||||
}
|
} else {
|
||||||
|
|
||||||
else{
|
|
||||||
throw new IllegalArgumentException("Not an existing algorithm type");
|
throw new IllegalArgumentException("Not an existing algorithm type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,10 +34,11 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||||
public class JwtSigningAndValidationServiceDefault extends AbstractJwtSigningAndValidationService implements
|
public class JwtSigningAndValidationServiceDefault extends AbstractJwtSigningAndValidationService implements
|
||||||
JwtSigningAndValidationService, InitializingBean {
|
JwtSigningAndValidationService, InitializingBean {
|
||||||
|
|
||||||
@Autowired ConfigurationPropertiesBean configBean;
|
@Autowired
|
||||||
|
private ConfigurationPropertiesBean configBean;
|
||||||
|
|
||||||
// map of identifier to signer
|
// map of identifier to signer
|
||||||
Map<String, ? extends JwtSigner> signers = new HashMap<String, JwtSigner>();
|
private Map<String, ? extends JwtSigner> signers = new HashMap<String, JwtSigner>();
|
||||||
|
|
||||||
private static Log logger = LogFactory
|
private static Log logger = LogFactory
|
||||||
.getLog(JwtSigningAndValidationServiceDefault.class);
|
.getLog(JwtSigningAndValidationServiceDefault.class);
|
||||||
|
|
|
@ -89,6 +89,7 @@ public class KeyStore implements InitializingBean {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: a more specific exception perhaps? is an empty keystore even an exception?
|
||||||
if (keystore.size() == 0) {
|
if (keystore.size() == 0) {
|
||||||
throw new Exception("Keystore is empty; it has no entries");
|
throw new Exception("Keystore is empty; it has no entries");
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,7 @@ public class Utility {
|
||||||
return issuer;
|
return issuer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: this should use a rest template and sould not throw Exception
|
||||||
public static List<Jwk> retrieveJwk(URL path) throws Exception {
|
public static List<Jwk> retrieveJwk(URL path) throws Exception {
|
||||||
List<Jwk> keys = new ArrayList<Jwk>();
|
List<Jwk> keys = new ArrayList<Jwk>();
|
||||||
|
|
||||||
|
@ -95,6 +96,7 @@ public class Utility {
|
||||||
return keys;
|
return keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: this should use a rest template and sould not throw Exception
|
||||||
public static Key retrieveX509Key(URL url) throws Exception {
|
public static Key retrieveX509Key(URL url) throws Exception {
|
||||||
|
|
||||||
CertificateFactory factory = CertificateFactory.getInstance("X.509");
|
CertificateFactory factory = CertificateFactory.getInstance("X.509");
|
||||||
|
@ -104,6 +106,7 @@ public class Utility {
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: this should use a rest template and sould not throw Exception
|
||||||
public static Key retrieveJwkKey(URL url) throws Exception {
|
public static Key retrieveJwkKey(URL url) throws Exception {
|
||||||
|
|
||||||
JsonParser parser = new JsonParser();
|
JsonParser parser = new JsonParser();
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
package org.mitre.swd.view;
|
package org.mitre.swd.view;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -44,7 +45,7 @@ public class XrdJsonResponse extends AbstractView {
|
||||||
* @see org.springframework.web.servlet.view.AbstractView#renderMergedOutputModel(java.util.Map, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
|
* @see org.springframework.web.servlet.view.AbstractView#renderMergedOutputModel(java.util.Map, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
|
protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) {
|
||||||
Gson gson = new GsonBuilder().setExclusionStrategies(new ExclusionStrategy() {
|
Gson gson = new GsonBuilder().setExclusionStrategies(new ExclusionStrategy() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -67,7 +68,14 @@ public class XrdJsonResponse extends AbstractView {
|
||||||
|
|
||||||
response.setContentType("application/json");
|
response.setContentType("application/json");
|
||||||
|
|
||||||
Writer out = response.getWriter();
|
Writer out;
|
||||||
|
try {
|
||||||
|
out = response.getWriter();
|
||||||
|
} catch (IOException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
return; // if we can't get the writer, this is pointless
|
||||||
|
}
|
||||||
|
|
||||||
Map<String, String> links = (Map<String, String>) model.get("links");
|
Map<String, String> links = (Map<String, String>) model.get("links");
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue