diff options
| author | Thomas Lenz <thomas.lenz@egiz.gv.at> | 2019-12-04 19:43:32 +0100 | 
|---|---|---|
| committer | Thomas Lenz <thomas.lenz@egiz.gv.at> | 2019-12-04 19:43:32 +0100 | 
| commit | 759ac5f42c6aff901dbeede4fbf1a1d2e08cad0f (patch) | |
| tree | 2132024fc058b1ef5338bf50df575a3244cc3f9f /eaaf_core_utils/src/main | |
| parent | 4f15bdc45b08724d20c66c9fd74ea6a43a03c32f (diff) | |
| download | EAAF-Components-759ac5f42c6aff901dbeede4fbf1a1d2e08cad0f.tar.gz EAAF-Components-759ac5f42c6aff901dbeede4fbf1a1d2e08cad0f.tar.bz2 EAAF-Components-759ac5f42c6aff901dbeede4fbf1a1d2e08cad0f.zip | |
common EGIZ code-style refactoring
Diffstat (limited to 'eaaf_core_utils/src/main')
22 files changed, 2014 insertions, 2058 deletions
| diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/support/SecureRandomHolder.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/support/SecureRandomHolder.java index a297367f..8584d63f 100644 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/support/SecureRandomHolder.java +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/support/SecureRandomHolder.java @@ -1,61 +1,57 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ,   - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.   * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at:   * https://joinup.ec.europa.eu/news/understanding-eupl-v12   * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - *   - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ +  package at.gv.egiz.eaaf.core.impl.idp.process.support;  import java.security.NoSuchAlgorithmException;  import java.security.SecureRandom;  /** - * Holder for a secure random instance following the initialization on demand holder design pattern. The secure random - * instance is a singleton that is initialized on first usage. - *  + * Holder for a secure random instance following the initialization on demand holder design pattern. + * The secure random instance is a singleton that is initialized on first usage. + *   * @author tknall - *  + *   */  public class SecureRandomHolder { -	private SecureRandomHolder() { -	} - -	private static final SecureRandom SRND_INSTANCE; -	static { -		try { -			SRND_INSTANCE = SecureRandom.getInstance("SHA1PRNG"); -		} catch (NoSuchAlgorithmException e) { -			throw new RuntimeException("Unable to instantiate SHA1PRNG.", e); -		} -	} - -	/** -	 * Returns a secure random generator instance. -	 * @return The secure random instance. -	 */ -	public static SecureRandom getInstance() { -		return SecureRandomHolder.SRND_INSTANCE; -	} - -}
\ No newline at end of file +  private SecureRandomHolder() { + +  } + +  private static final SecureRandom SRND_INSTANCE; + +  static { +    try { +      SRND_INSTANCE = SecureRandom.getInstance("SHA1PRNG"); +    } catch (final NoSuchAlgorithmException e) { +      throw new RuntimeException("Unable to instantiate SHA1PRNG.", e); +    } +  } + +  /** +   * Returns a secure random generator instance. +   * +   * @return The secure random instance. +   */ +  public static SecureRandom getInstance() { +    return SecureRandomHolder.SRND_INSTANCE; +  } + +} diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/logging/SimpleStatusMessager.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/logging/SimpleStatusMessager.java index d36c79b9..5715a7b6 100644 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/logging/SimpleStatusMessager.java +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/logging/SimpleStatusMessager.java @@ -1,44 +1,44 @@  package at.gv.egiz.eaaf.core.impl.logging;  import java.text.MessageFormat; -  import at.gv.egiz.eaaf.core.api.IStatusMessenger;  /** - * Simple {@link IStatusMessenger} implementation that formats messages by using {@link MessageFormat}  - *  + * Simple {@link IStatusMessenger} implementation that formats messages by using. + * {@link MessageFormat} + *   * @author tlenz   *   */  public class SimpleStatusMessager implements IStatusMessenger { -	private static final String NOTSUPPORTED = "Error response-codes not supported"; -	private static final String NULLMESSAGE = "No error-message provided"; -	 -	@Override -	public String getMessage(String messageId, Object[] parameters) {		 -		return getMessageWithoutDefault(messageId, parameters); -		 -	} - -	@Override -	public String getMessageWithoutDefault(String messageId, Object[] parameters) { -		if (messageId != null) { -			return MessageFormat.format(messageId, parameters); -			 -		} -		 -		return NULLMESSAGE; -	} - -	@Override -	public String getResponseErrorCode(Throwable throwable) { -		return NOTSUPPORTED; -	} - -	@Override -	public String mapInternalErrorToExternalError(String intErrorCode) { -		return NOTSUPPORTED; -	} +  private static final String NOTSUPPORTED = "Error response-codes not supported"; +  private static final String NULLMESSAGE = "No error-message provided"; + +  @Override +  public String getMessage(final String messageId, final Object[] parameters) { +    return getMessageWithoutDefault(messageId, parameters); + +  } + +  @Override +  public String getMessageWithoutDefault(final String messageId, final Object[] parameters) { +    if (messageId != null) { +      return MessageFormat.format(messageId, parameters); + +    } + +    return NULLMESSAGE; +  } + +  @Override +  public String getResponseErrorCode(final Throwable throwable) { +    return NOTSUPPORTED; +  } + +  @Override +  public String mapInternalErrorToExternalError(final String intErrorCode) { +    return NOTSUPPORTED; +  }  } diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/ArrayUtils.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/ArrayUtils.java index 8585bc05..1da82f43 100644 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/ArrayUtils.java +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/ArrayUtils.java @@ -1,44 +1,42 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ,   - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.   * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at:   * https://joinup.ec.europa.eu/news/understanding-eupl-v12   * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - *   - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. + */ +  package at.gv.egiz.eaaf.core.impl.utils;  import java.util.List;  public class ArrayUtils { -	/** -	 * Check if a String 's' is part of a List 'l' in qualsIgnoreCase mode -	 *  -	 * @param s Search String -	 * @param l List of String elements -	 * @return true if 's' is in 'l', otherwise false -	 */ -	public static boolean containsCaseInsensitive(String s, List<String> l){ -		if (l == null || s == null) -			return false; -		 -        return l.stream().anyMatch(x -> x.equalsIgnoreCase(s)); -         +  /** +   * Check if a String 's' is part of a List 'l' in qualsIgnoreCase mode. +   * +   * @param s Search String +   * @param l List of String elements +   * @return true if 's' is in 'l', otherwise false +   */ +  public static boolean containsCaseInsensitive(final String s, final List<String> l) { +    if (l == null || s == null) { +      return false;      } +    return l.stream().anyMatch(x -> x.equalsIgnoreCase(s)); + +  } +  } diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/DataURLBuilder.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/DataURLBuilder.java deleted file mode 100644 index a81fafbc..00000000 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/DataURLBuilder.java +++ /dev/null @@ -1,113 +0,0 @@ -/******************************************************************************* - * Copyright 2014 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - *  - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * http://www.osor.eu/eupl/ - *  - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - *  - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - ******************************************************************************/ -/* - * Copyright 2003 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * http://www.osor.eu/eupl/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - */ - - -package at.gv.egiz.eaaf.core.impl.utils; - -import org.apache.commons.lang3.StringUtils; - -import at.gv.egiz.eaaf.core.api.data.EAAFConstants; - -/** - * Builds a DataURL parameter meant for the security layer implementation - * to respond to. - *  - * @author Paul Ivancsics - * @version $Id$ - */ -public class DataURLBuilder { -	 -  /** -   * Constructor for DataURLBuilder. -   */ -  public DataURLBuilder() { -    super(); -  } -   -  /** -   * Constructs a data URL for <code>VerifyIdentityLink</code> or <code>VerifyAuthenticationBlock</code>,  -   * including the <code>MOASessionID</code> as a parameter. -   *  -   * @param authBaseURL base URL (context path) of the MOA ID Authentication component, -   * 				 including a trailing <code>'/'</code> -   * @param authServletName request part of the data URL -   * @param pendingReqId sessionID to be included in the dataURL -   * @return String -   */ -  public String buildDataURL(String authBaseURL, String authServletName, String pendingReqId) { -		String dataURL;		 -		if (!authBaseURL.endsWith("/")) -			authBaseURL += "/"; -		 -		if (authServletName.startsWith("/")) -			authServletName = authServletName.substring(1); -		 -		dataURL = authBaseURL + authServletName; - -		if (StringUtils.isNotEmpty(pendingReqId)) -			dataURL = addParameter(dataURL, EAAFConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID, pendingReqId); -		 -  	return dataURL; -  } - -  /** -   * Method addParameter. -   * @param urlString represents the url  -   * @param paramname is the parameter to be added -   * @param value is the value of that parameter -   * @return String -   */ -  private String addParameter(String urlString, String paramname, String value) { -    String url = urlString; -    if (paramname != null) { -      if (url.indexOf("?") < 0) -        url += "?"; -      else -        url += "&"; -      url += paramname + "=" + value; -    } -    return url; -  } -} diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/DataUrlBuilder.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/DataUrlBuilder.java new file mode 100644 index 00000000..a72e07dd --- /dev/null +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/DataUrlBuilder.java @@ -0,0 +1,91 @@ +/* + * Copyright 2014 Federal Chancellery Austria MOA-ID has been developed in a cooperation between + * BRZ, the Federal Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. + */ + +package at.gv.egiz.eaaf.core.impl.utils; + +import org.apache.commons.lang3.StringUtils; + +import at.gv.egiz.eaaf.core.api.data.EAAFConstants; + +/** + * Builds a DataURL parameter meant for the security layer implementation to respond to. + * + * @author Paul Ivancsics + * @version $Id$ + */ +public class DataUrlBuilder { + +  /** +   * Constructor for DataURLBuilder. +   */ +  public DataUrlBuilder() { +    super(); +  } + +  /** +   * Constructs a data URL for <code>VerifyIdentityLink</code> or +   * <code>VerifyAuthenticationBlock</code>, including the <code>MOASessionID</code> as a parameter. +   * +   * @param authBaseUrl base URL (context path) of the MOA ID Authentication component, including a +   *        trailing <code>'/'</code> +   * @param authServletName request part of the data URL +   * @param pendingReqId sessionID to be included in the dataURL +   * @return String +   */ +  public String buildDataUrl(String authBaseUrl, String authServletName, +      final String pendingReqId) { +    String dataUrl; +    if (!authBaseUrl.endsWith("/")) { +      authBaseUrl += "/"; +    } + +    if (authServletName.startsWith("/")) { +      authServletName = authServletName.substring(1); +    } + +    dataUrl = authBaseUrl + authServletName; + +    if (StringUtils.isNotEmpty(pendingReqId)) { +      dataUrl = +          addParameter(dataUrl, EAAFConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID, pendingReqId); +    } + +    return dataUrl; +  } + +  /** +   * Method addParameter. +   *  +   * @param urlString represents the url +   * @param paramname is the parameter to be added +   * @param value is the value of that parameter +   * @return String +   */ +  private String addParameter(final String urlString, final String paramname, final String value) { +    String url = urlString; +    if (paramname != null) { +      if (url.indexOf("?") < 0) { +        url += "?"; +      } else { +        url += "&"; +      } +      url += paramname + "=" + value; +    } +    return url; +  } +} diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/FileUtils.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/FileUtils.java index 6ac51ac4..943d3dad 100644 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/FileUtils.java +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/FileUtils.java @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ,   - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.   * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at:   * https://joinup.ec.europa.eu/news/understanding-eupl-v12   * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - *   - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. + */ +  package at.gv.egiz.eaaf.core.impl.utils; @@ -38,22 +31,22 @@ import java.io.OutputStream;  import java.net.MalformedURLException;  import java.net.URI;  import java.net.URL; -  import org.apache.commons.lang3.StringUtils;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory;  public class FileUtils { -	private static final Logger log = LoggerFactory.getLogger(FileUtils.class); -	 -	 +  private static final Logger log = LoggerFactory.getLogger(FileUtils.class); + +    /**     * Reads a file, given by URL, into a byte array. +   *     * @param urlString file URL     * @return file content     * @throws IOException on any exception thrown     */ -  public static byte[] readURL(String urlString) throws IOException {	   +  public static byte[] readUrl(final String urlString) throws IOException {      final URL url = new URL(urlString);      final InputStream in = new BufferedInputStream(url.openStream());      final byte[] content = StreamUtils.readStream(in); @@ -63,114 +56,142 @@ public class FileUtils {    /**     * Reads a file from a resource. +   *     * @param name resource name     * @return file content as a byte array     * @throws IOException on any exception thrown     */ -  public static byte[] readResource(String name) throws IOException { +  public static byte[] readResource(final String name) throws IOException {      final ClassLoader cl = FileUtils.class.getClassLoader();      final BufferedInputStream in = new BufferedInputStream(cl.getResourceAsStream(name));      final byte[] content = StreamUtils.readStream(in);      in.close();      return content;    } +    /**     * Reads a file from a resource. +   *     * @param name filename     * @param encoding character encoding     * @return file content     * @throws IOException on any exception thrown     */ -  public static String readResource(String name, String encoding) throws IOException { +  public static String readResource(final String name, final String encoding) throws IOException {      final byte[] content = readResource(name);      return new String(content, encoding);    } -   -   -	/** -	 * Returns the absolute URL of a given url which is relative to the parameter root -	 * @param url -	 * @param root -	 * @return String -	 * @throws MalformedURLException  -	 */ -	public static String makeAbsoluteURL(String url, URI root) throws MalformedURLException { -		if (root != null) -			return makeAbsoluteURL(url, root.toURL().toString()); -		else -			return makeAbsoluteURL(url, StringUtils.EMPTY); - -	}   -   -	/** -	 * Returns the absolute URL of a given url which is relative to the parameter root -	 * @param url -	 * @param root -	 * @return String -	 */ -	public static String makeAbsoluteURL(String url, String root) { -		//if url is relative to rootConfigFileDirName make it absolute 					 -		 -		log.trace("Making AbsoluteURL URL: " + url + " Root-Path: " + root); -		 -		if (StringUtils.isEmpty(root)) -			root = null; -		 -		File keyFile; -		String newURL = url; -		 -		if(null == url) return  null; -     -		if (url.startsWith("http:") || url.startsWith("https:") || url.startsWith("file:")  -				|| url.startsWith("ftp:") || url.startsWith("classpath:")) { -			return url; -			 -		} else { -			// check if absolute - if not make it absolute -			keyFile = new File(url); -			if (!keyFile.isAbsolute()) { -				keyFile = new File(root, url); - -				if (keyFile.toString().startsWith("file:")) -					newURL = keyFile.toString(); -         -				else -					newURL = keyFile.toURI().toString(); -         -			} -			return newURL; -		} -	}   -	 -	 -	 private static void copy( InputStream fis, OutputStream fos ) -	  { -	    try -	    { -	      final byte[] buffer = new byte[ 0xFFFF ]; -	      for ( int len; (len = fis.read(buffer)) != -1; ) -	        fos.write( buffer, 0, len ); -	    } -	    catch( final IOException e ) { -	      System.err.println( e ); -	    } -	    finally { -	      if ( fis != null ) -	        try { fis.close(); } catch ( final IOException e ) { e.printStackTrace(); } -	      if ( fos != null ) -	        try { fos.close(); } catch ( final IOException e ) { e.printStackTrace(); } -	    } -	  } -	  -	 public static void copyFile(File src, File dest) -	  { -	    try -	    { -	      copy( new FileInputStream( src ), new FileOutputStream( dest ) ); -	    } -	    catch( final IOException e ) { -	      e.printStackTrace(); -	    } -	  } -   + + +  /** +   * Returns the absolute URL of a given url which is relative to the parameter root. +   * +   * @param url Filepath +   * @param root configuration root context +   * @return absolut filepath +   * @throws MalformedURLException In case of a filepath error +   */ +  public static String makeAbsoluteUrl(final String url, final URI root) +      throws MalformedURLException { +    if (root != null) { +      return makeAbsoluteUrl(url, root.toURL().toString()); +    } else { +      return makeAbsoluteUrl(url, StringUtils.EMPTY); +    } + +  } + +  /** +   * Returns the absolute URL of a given url which is relative to the parameter root. +   * +   * @param url Filepath +   * @param root configuration root context +   * @return absolut filepath +   */ +  public static String makeAbsoluteUrl(final String url, String root) { +    // if url is relative to rootConfigFileDirName make it absolute + +    log.trace("Making AbsoluteURL URL: " + url + " Root-Path: " + root); + +    if (StringUtils.isEmpty(root)) { +      root = null; +    } + +    File keyFile; +    String newUrl = url; + +    if (null == url) { +      return null; +    } + +    if (url.startsWith("http:") || url.startsWith("https:") || url.startsWith("file:") +        || url.startsWith("ftp:") || url.startsWith("classpath:")) { +      return url; + +    } else { +      // check if absolute - if not make it absolute +      keyFile = new File(url); +      if (!keyFile.isAbsolute()) { +        keyFile = new File(root, url); + +        if (keyFile.toString().startsWith("file:")) { +          newUrl = keyFile.toString(); +        } else { +          newUrl = keyFile.toURI().toString(); +        } + +      } +      return newUrl; +    } +  } + + +  private static void copy(final InputStream fis, final OutputStream fos) { +    try { +      final byte[] buffer = new byte[0xFFFF]; +      for (int len; (len = fis.read(buffer)) != -1;) { +        fos.write(buffer, 0, len); +      } +    } catch (final IOException e) { +      System.err.println(e); + +    } +  } + +  /** +   * Copy file from source to destination. +   * +   * @param src File source +   * @param dest file destination +   */ +  public static void copyFile(final File src, final File dest) { +    InputStream fis = null; +    OutputStream fos = null; + +    try { +      fis = new FileInputStream(src); +      fos = new FileOutputStream(src); +      copy(fis, fos); + +    } catch (final IOException e) { +      e.printStackTrace(); + +    } finally { +      if (fis != null) { +        try { +          fis.close(); +        } catch (final IOException e) { +          e.printStackTrace(); +        } +      } +      if (fos != null) { +        try { +          fos.close(); +        } catch (final IOException e) { +          e.printStackTrace(); +        } +      } +    } +  } +  } diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HTTPUtils.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HTTPUtils.java deleted file mode 100644 index cf1abaa7..00000000 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HTTPUtils.java +++ /dev/null @@ -1,178 +0,0 @@ -/******************************************************************************* - * Copyright 2014 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - *  - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * http://www.osor.eu/eupl/ - *  - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - *  - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - ******************************************************************************/ -/* - * Copyright 2003 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * http://www.osor.eu/eupl/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - */ - - -package at.gv.egiz.eaaf.core.impl.utils; - -import javax.servlet.http.HttpServletRequest; - -import org.apache.commons.lang3.StringUtils; - - -/** - *  - * @author Rudolf Schamberger - * - */ -public class HTTPUtils { - -//  /** -//   * Utility used to obtainin correct encoded HTTP content. -//   * Reads a given Content adressed by HTTP-URL into String.  -//   * Content encoding is considered by using the Content-Type HTTP header charset value. -//   * @param URL HTTP URL to read from. -//   * @return String representation of content -//   * @throws IOException on data-reading problems -//   */ -//  public static String readHttpURL(String URL)  -//    throws IOException { -//       -//    URL url = new URL(URL); -//    HttpURLConnection conn = (HttpURLConnection)url.openConnection(); -//    conn.setRequestMethod("GET"); -//    String contentType = conn.getContentType(); -//    RE regExp = null; -//    try { -//        regExp = new RE("(;.*charset=)(\"*)(.*[^\"])"); -//    } catch (RESyntaxException e) { -//        //RESyntaxException is not possible = expr. is costant -//    } -//    boolean charsetSupplied = regExp.match(contentType); -//    String encoding = "ISO-8859-1"; 		//default HTTP encoding  -//    if (charsetSupplied) { -//      encoding = regExp.getParen(3); -//    } -//    InputStream instream = new BufferedInputStream(conn.getInputStream()); -//    InputStreamReader isr = new InputStreamReader(instream, encoding); -//    Reader in = new BufferedReader(isr); -//    int ch; -//  	StringBuffer buffer = new StringBuffer(); -//    while ((ch = in.read()) > -1) { -//  		buffer.append((char)ch); -//  	}      -//    in.close(); -//    conn.disconnect(); -//    return buffer.toString(); -//  } -   -  	/** -  	 * Helper method to retrieve server URL including context path -  	 * @param request HttpServletRequest -  	 * @return Server URL including context path (e.g. http://localhost:8443/moa-id-auth -  	 */ -  	public static String getBaseURL(HttpServletRequest request) { -		StringBuffer buffer = new StringBuffer(getServerURL(request)); -		 -	    // add context path if available -	    String contextPath = request.getContextPath(); -	    if (!StringUtils.isEmpty(contextPath)) { -	    	buffer.append(contextPath); -	    } -		 -		return buffer.toString();  -	} -	 -  	/** -  	 * Helper method to retrieve server URL -  	 * @param request HttpServletRequest -  	 * @return Server URL (e.g. http://localhost:8443) -  	 */ -	public static String getServerURL(HttpServletRequest request) { -		StringBuffer buffer = new StringBuffer(); -		 -		// get protocol -		String protocol = request.getScheme(); -		buffer.append(protocol).append("://"); -		 -		// server name -		buffer.append(request.getServerName()); -		 -		// add port if necessary -		int port = request.getServerPort(); -	    if ((protocol.equals("http") && port != 80) || (protocol.equals("https") && port != 443)) { -	    	buffer.append(':'); -	    	buffer.append(port); -	    } -	 -	    return buffer.toString();  -	} -	 -	/** -	 * Extract the IDP PublicURLPrefix from authrequest -	 *  -	 * @param req HttpServletRequest -	 * @return PublicURLPrefix <String> which ends always without / -	 */ -	public static String extractAuthURLFromRequest(HttpServletRequest req) { -	    String authURL = req.getScheme() + "://" + req.getServerName(); -	    if ((req.getScheme().equalsIgnoreCase("https") && req.getServerPort()!=443) || (req.getScheme().equalsIgnoreCase("http") && req.getServerPort()!=80)) {  -	      authURL = authURL.concat(":" + req.getServerPort()); -	    } -	    authURL = authURL.concat(req.getContextPath()); -	    return authURL; -		 -	} -	 -	/** -	 * Extract the IDP requested URL from authrequest -	 *  -	 * @param req HttpServletRequest -	 * @return RequestURL <String> which ends always without / -	 */  -	public static String extractAuthServletPathFromRequest(HttpServletRequest req) { -	    return extractAuthURLFromRequest(req).concat(req.getServletPath()); -	 	 -	} -	 -	public static String addURLParameter(String url, String paramname, -			String paramvalue) { -		String param = paramname + "=" + paramvalue; -		if (url.indexOf("?") < 0) -			return url + "?" + param; -		else -			return url + "&" + param; -	} - -} diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HttpClientFactory.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HttpClientFactory.java index a8cfa7c1..4e8be52e 100644 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HttpClientFactory.java +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HttpClientFactory.java @@ -8,11 +8,11 @@ import java.security.KeyStoreException;  import java.security.NoSuchAlgorithmException;  import java.security.UnrecoverableKeyException;  import java.security.cert.CertificateException; -  import javax.annotation.PostConstruct;  import javax.net.ssl.HostnameVerifier;  import javax.net.ssl.SSLContext; - +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException;  import org.apache.commons.lang3.StringUtils;  import org.apache.http.HttpRequest;  import org.apache.http.HttpResponse; @@ -44,339 +44,378 @@ import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.core.io.Resource;  import org.springframework.core.io.ResourceLoader; -import at.gv.egiz.eaaf.core.api.idp.IConfiguration; -import at.gv.egiz.eaaf.core.exceptions.EAAFConfigurationException; -  public class HttpClientFactory implements IHttpClientFactory { -	private static final Logger log = LoggerFactory.getLogger(HttpClientFactory.class);	 -	@Autowired(required=true) private IConfiguration basicConfig; -	@Autowired(required=true) ResourceLoader resourceLoader; -	 -	public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_USE = "client.http.connection.pool.use"; -	public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXTOTAL = "client.http.connection.pool.maxtotal"; -	public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXPERROUTE = "client.http.connection.pool.maxperroute"; -	public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_SOCKET = "client.http.connection.timeout.socket"; -	public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_CONNECTION = "client.http.connection.timeout.connection"; -	public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_REQUEST = "client.http.connection.timeout.request"; -	public static final String PROP_CONFIG_CLIENT_HTTP_SSL_HOSTNAMEVERIFIER_TRUSTALL = "client.http.ssl.hostnameverifier.trustall"; -	 -	public static final String PROP_CONFIG_CLIENT_MODE = "client.authmode"; -	public static final String PROP_CONFIG_CLIENT_AUTH_HTTP_USERNAME = "client.auth.http.username"; -	public static final String PROP_CONFIG_CLIENT_AUTH_HTTP_PASSORD = "client.auth.http.password"; -	public static final String PROP_CONFIG_CLIENT_AUTH_SSL_KEYSTORE_PATH = "client.auth.ssl.keystore.path"; -	public static final String PROP_CONFIG_CLIENT_AUTH_SSL_KEYSTORE_PASSORD = "client.auth.ssl.keystore.password"; -	public static final String PROP_CONFIG_CLIENT_AUTH_SSL_KEYSTORE_TYPE = "client.auth.ssl.keystore.type"; -	public static final String PROP_CONFIG_CLIENT_AUTH_SSL_KEY_PASSWORD = "client.auth.ssl.key.password"; -	public static final String PROP_CONFIG_CLIENT_AUTH_SSL_KEY_ALIAS = "client.auth.ssl.key.alias"; -	 -	// default configuration values -	public static final String DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_SOCKET = "15"; -	public static final String DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_CONNECTION = "15"; -	public static final String DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_REQUEST = "30"; -	public static final String DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXTOTAL = "500"; -	public static final String DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXPERROUTE = "100"; -	 -	public enum ClientAuthMode { -		NONE("none"), -		PASSWORD("password"), -		SSL("ssl"); -		 -		private final String mode; -		 -		private ClientAuthMode(String mode) { -			this.mode = mode; -		} -		 -		/** -		 * Get the PVP mode -		 *  -		 * @return -		 */ -		public String getMode() { -			return this.mode; -		} -		 -		public static ClientAuthMode fromString(String s) { -			try { -				return ClientAuthMode.valueOf(s.toUpperCase()); -				 -		    } catch (IllegalArgumentException|NullPointerException e) { -		    	return null; -		    } -		} -		 -		@Override -		public String toString() { -			return getMode(); -			 -		} -		 -	}; -	 -	public enum KeyStoreType { -		PKCS12("pkcs12"), -		JKS("jks"); -		 -		private final String type; -		 -		private KeyStoreType (String type) { -			this.type = type; -		} -		 -		/** -		 * Get the PVP mode -		 *  -		 * @return -		 */ -		public String getType() { -			return this.type; -		} -		 -		public static KeyStoreType fromString(String s) { -			try { -				return KeyStoreType.valueOf(s.toUpperCase()); -				 -		    } catch (IllegalArgumentException|NullPointerException e) { -		    	return null; -		    } -		} -		 -		@Override -		public String toString() { -			return getType(); -			 -		} -		 -	}; -	 -	private HttpClientBuilder httpClientBuilder = null; -	 -	/* (non-Javadoc) -	 * @see at.gv.egiz.eaaf.core.impl.utils.IHttpClientFactory#getHttpClient() -	 */ -	@Override -	public CloseableHttpClient getHttpClient() { -		return getHttpClient(true); -		 -	} -	 -	@Override -	public CloseableHttpClient getHttpClient(boolean followRedirects) { -		RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();  -		if (!followRedirects) -			redirectStrategy = new RedirectStrategy() { -				 -				@Override -				public boolean isRedirected(HttpRequest request, HttpResponse response, HttpContext context) -						throws ProtocolException { -					return false; -				} -				 -				@Override -				public HttpUriRequest getRedirect(HttpRequest request, HttpResponse response, HttpContext context) -						throws ProtocolException { -					return null; -				} -			}; -		  -		return httpClientBuilder -				.setRedirectStrategy(redirectStrategy) -				.build();			 -									 -	} -	 -	@PostConstruct -	private void initalize() { -		//initialize http client  -		log.trace("Initializing HTTP Client-builder ... "); -		httpClientBuilder = HttpClients.custom(); -		  -		//set default request configuration -		final RequestConfig requestConfig = RequestConfig.custom() -											.setConnectTimeout(Integer.valueOf(basicConfig.getBasicConfiguration( -													PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_CONNECTION,  -													DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_CONNECTION)) * 1000) -											.setConnectionRequestTimeout(Integer.valueOf(basicConfig.getBasicConfiguration( -													PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_REQUEST,  -													DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_REQUEST)) * 1000) -											.setSocketTimeout(Integer.valueOf(basicConfig.getBasicConfiguration( -													PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_SOCKET,  -													DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_SOCKET)) * 1000) -											.build();		 -		httpClientBuilder.setDefaultRequestConfig(requestConfig); -				 -		ClientAuthMode clientAuthMode = ClientAuthMode.fromString( -				basicConfig.getBasicConfiguration(PROP_CONFIG_CLIENT_MODE, ClientAuthMode.NONE.getMode())); -		if (clientAuthMode == null) { -			log.warn("Can Not parse ClientAuthMode! Set mode to default value"); -			clientAuthMode = ClientAuthMode.NONE; -			 -		} -				 -		//inject basic http authentication if required -		log.info("Client authentication-mode is set to: {}", clientAuthMode); -		injectBasicAuthenticationIfRequired(clientAuthMode); -				 -		//inject authentication if required -		final LayeredConnectionSocketFactory sslConnectionFactory = getSSLContext(clientAuthMode); -		 -		//set  pool connection if required -		injectConnectionPoolIfRequired(sslConnectionFactory); -				 -				 -	} - -	private void injectBasicAuthenticationIfRequired(ClientAuthMode clientAuthMode) { -		if (clientAuthMode.equals(ClientAuthMode.PASSWORD)) { -			final CredentialsProvider provider = new BasicCredentialsProvider(); -			 -			final String username = basicConfig.getBasicConfiguration(PROP_CONFIG_CLIENT_AUTH_HTTP_USERNAME); -			final String password = basicConfig.getBasicConfiguration(PROP_CONFIG_CLIENT_AUTH_HTTP_PASSORD); -			 -			if (StringUtils.isEmpty(username)) { -				log.warn("Http basic authentication was activated but NOT username was set!"); -				 -			} -			 -			log.trace("Injecting basic authentication with username: {} and password: {}", username, password);						 -			final UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(username, password); -			provider.setCredentials(AuthScope.ANY, credentials); -			httpClientBuilder.setDefaultCredentialsProvider(provider);						 -			log.info("Basic http authentication was injected with username: {}", username); -			 -		} else { -			log.trace("Injection of Http Basic authentication was skipped"); -			 -		} -		 -	} -	 -	private SSLContext buildSSLContextWithSSLClientAuthentication() throws KeyManagementException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException, EAAFConfigurationException  { -		log.trace("Injecting SSL client-authentication into http client ... ");				 -		final KeyStore keystore = getSSLAuthKeyStore(); -		final String keyPasswordString = basicConfig.getBasicConfiguration(PROP_CONFIG_CLIENT_AUTH_SSL_KEY_PASSWORD); -		log.trace("Open SSL Client-Auth keystore with password: {}", keyPasswordString); -		final char[] keyPassword = (keyPasswordString == null) ? StringUtils.EMPTY.toCharArray() : keyPasswordString.toCharArray(); -		return SSLContexts.custom().loadKeyMaterial(keystore, keyPassword).build(); -		 -	} -	 -	private KeyStore getSSLAuthKeyStore() throws EAAFConfigurationException { -		final KeyStoreType keyStoreType = KeyStoreType.fromString( -				basicConfig.getBasicConfiguration(PROP_CONFIG_CLIENT_AUTH_SSL_KEYSTORE_TYPE, KeyStoreType.PKCS12.getType())); -		final String localKeyStorePath = basicConfig.getBasicConfiguration(PROP_CONFIG_CLIENT_AUTH_SSL_KEYSTORE_PATH, StringUtils.EMPTY); -		final String keyStorePassword = basicConfig.getBasicConfiguration(PROP_CONFIG_CLIENT_AUTH_SSL_KEYSTORE_PASSORD, StringUtils.EMPTY); -		 -		try {			 -			log.debug("Open keyStore with type: {}", keyStoreType);	 -			KeyStore clientStore; -			if (keyStoreType.equals(KeyStoreType.PKCS12)) { -				clientStore = KeyStore.getInstance("pkcs12");			 -			} else {  -				clientStore = KeyStore.getInstance("JKS");			 -			} -				 -		 -			log.debug("Read keyStore path: {} from configuration", localKeyStorePath);		 -			if (StringUtils.isNotEmpty(localKeyStorePath)) {			 -				final String absFilePath = FileUtils.makeAbsoluteURL(localKeyStorePath, basicConfig.getConfigurationRootDirectory()); -				final Resource ressource = resourceLoader.getResource(absFilePath); -				final InputStream is = ressource.getInputStream();	 -				log.trace("Load keyStore: {} with password: {}", absFilePath, keyStorePassword); -				clientStore.load(is, keyStorePassword.toCharArray()); -				is.close(); -				 -				return clientStore; -				 -			} else { -				log.warn("Path to keyStore for SSL Client-Authentication is empty or null"); -				throw new EAAFConfigurationException("Path to keyStore for SSL Client-Authentication is empty or null", new Object[] {}); -				 -			} -			 -		} catch (final KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e) { -			log.warn("Can NOT read keyStore: {} from filesystem", localKeyStorePath, null,  e); -			throw new EAAFConfigurationException("Can NOT read keyStore: {} from filesystem", new Object[] {localKeyStorePath}, e); -			 -		} -				 -	} - -	private LayeredConnectionSocketFactory getSSLContext(ClientAuthMode clientAuthMode) {				 -		SSLContext sslContext = null;		 -		try { -			if (clientAuthMode.equals(ClientAuthMode.SSL)) { -				sslContext = buildSSLContextWithSSLClientAuthentication(); -										 -			} else { -				log.trace("Initializing default SSL Context ... "); -				sslContext = SSLContext.getDefault(); -			 -			} -		 -			//set hostname verifier -			HostnameVerifier hostnameVerifier = null; -			if (basicConfig.getBasicConfigurationBoolean( -					PROP_CONFIG_CLIENT_HTTP_SSL_HOSTNAMEVERIFIER_TRUSTALL,  -					false)) { -				hostnameVerifier = new NoopHostnameVerifier(); -				log.warn("HTTP client-builder deactivates SSL Host-name verification!"); -				 -			} -						 -			final LayeredConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext , hostnameVerifier);						 -			 -			return sslSocketFactory; -						 -		} catch (final NoSuchAlgorithmException | KeyManagementException | UnrecoverableKeyException | KeyStoreException | EAAFConfigurationException e) { -			log.warn("HTTP client-builder can NOT initialze SSL-Context", e); -						 -		} -		 -		log.info("HTTP client-builder successfuly initialized"); -		return null; -		 -	} - -	private void injectConnectionPoolIfRequired(LayeredConnectionSocketFactory sslConnectionFactory) { -		if (basicConfig.getBasicConfigurationBoolean( -				PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_USE,  -				true)) { -			PoolingHttpClientConnectionManager pool; -			 -			//set socketFactoryRegistry if SSLConnectionFactory is Set -			if (sslConnectionFactory != null) { -				final Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create() -			        .register("http", PlainConnectionSocketFactory.getSocketFactory()) -			        .register("https", sslConnectionFactory) -			        .build(); -				log.trace("Inject SSLSocketFactory into pooled connection");			 -				pool = new PoolingHttpClientConnectionManager(socketFactoryRegistry); -				 -			} else { -				pool = new PoolingHttpClientConnectionManager(); -				 -			} -			 -			pool.setDefaultMaxPerRoute(Integer.valueOf(basicConfig.getBasicConfiguration( -					PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXPERROUTE,  -					DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXPERROUTE)));			 -			pool.setMaxTotal(Integer.valueOf(basicConfig.getBasicConfiguration( -					PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXTOTAL,  -					DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXTOTAL))); -									 -			httpClientBuilder.setConnectionManager(pool); -			log.debug("Initalize http-client pool with, maxTotal: {} maxPerRoute: {}", pool.getMaxTotal(), pool.getDefaultMaxPerRoute()); -					 -		} else if (sslConnectionFactory != null) { -			log.trace("Inject SSLSocketFactory without connection pool"); -			httpClientBuilder.setSSLSocketFactory(sslConnectionFactory ); -			 -		} -			 -		 -	} - -	 -	 +  private static final Logger log = LoggerFactory.getLogger(HttpClientFactory.class); +  @Autowired(required = true) +  private IConfiguration basicConfig; +  @Autowired(required = true) +  ResourceLoader resourceLoader; + +  public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_USE = +      "client.http.connection.pool.use"; +  public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXTOTAL = +      "client.http.connection.pool.maxtotal"; +  public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXPERROUTE = +      "client.http.connection.pool.maxperroute"; +  public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_SOCKET = +      "client.http.connection.timeout.socket"; +  public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_CONNECTION = +      "client.http.connection.timeout.connection"; +  public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_REQUEST = +      "client.http.connection.timeout.request"; +  public static final String PROP_CONFIG_CLIENT_HTTP_SSL_HOSTNAMEVERIFIER_TRUSTALL = +      "client.http.ssl.hostnameverifier.trustall"; + +  public static final String PROP_CONFIG_CLIENT_MODE = "client.authmode"; +  public static final String PROP_CONFIG_CLIENT_AUTH_HTTP_USERNAME = "client.auth.http.username"; +  public static final String PROP_CONFIG_CLIENT_AUTH_HTTP_PASSORD = "client.auth.http.password"; +  public static final String PROP_CONFIG_CLIENT_AUTH_SSL_KEYSTORE_PATH = +      "client.auth.ssl.keystore.path"; +  public static final String PROP_CONFIG_CLIENT_AUTH_SSL_KEYSTORE_PASSORD = +      "client.auth.ssl.keystore.password"; +  public static final String PROP_CONFIG_CLIENT_AUTH_SSL_KEYSTORE_TYPE = +      "client.auth.ssl.keystore.type"; +  public static final String PROP_CONFIG_CLIENT_AUTH_SSL_KEY_PASSWORD = +      "client.auth.ssl.key.password"; +  public static final String PROP_CONFIG_CLIENT_AUTH_SSL_KEY_ALIAS = "client.auth.ssl.key.alias"; + +  // default configuration values +  public static final String DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_SOCKET = "15"; +  public static final String DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_CONNECTION = "15"; +  public static final String DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_REQUEST = "30"; +  public static final String DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXTOTAL = "500"; +  public static final String DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXPERROUTE = "100"; + +  public enum ClientAuthMode { +    NONE("none"), PASSWORD("password"), SSL("ssl"); + +    private final String mode; + +    private ClientAuthMode(final String mode) { +      this.mode = mode; +    } + +    /** +     * Get the PVP mode. +     * +     * @return +     */ +    public String getMode() { +      return this.mode; +    } + +    /** +     * Get http-client authentication mode from String representation. +     * +     * @param s Config parameter +     * @return +     */ +    public static ClientAuthMode fromString(final String s) { +      try { +        return ClientAuthMode.valueOf(s.toUpperCase()); + +      } catch (IllegalArgumentException | NullPointerException e) { +        return null; +      } +    } + +    @Override +    public String toString() { +      return getMode(); + +    } + +  } + +  public enum KeyStoreType { +    PKCS12("pkcs12"), JKS("jks"); + +    private final String type; + +    private KeyStoreType(final String type) { +      this.type = type; +    } + +    /** +     * Get the KeyStore type. +     * +     * @return +     */ +    public String getType() { +      return this.type; +    } + +    /** +     * Get Keystore type from configuration. +     * +     * @param s String representation for keyStore type +     * @return +     */ +    public static KeyStoreType fromString(final String s) { +      try { +        return KeyStoreType.valueOf(s.toUpperCase()); + +      } catch (IllegalArgumentException | NullPointerException e) { +        return null; +      } +    } + +    @Override +    public String toString() { +      return getType(); + +    } + +  } + +  private HttpClientBuilder httpClientBuilder = null; + +  /* +   * (non-Javadoc) +   * +   * @see at.gv.egiz.eaaf.core.impl.utils.IHttpClientFactory#getHttpClient() +   */ +  @Override +  public CloseableHttpClient getHttpClient() { +    return getHttpClient(true); + +  } + +  @Override +  public CloseableHttpClient getHttpClient(final boolean followRedirects) { +    RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); +    if (!followRedirects) { +      redirectStrategy = new RedirectStrategy() { + +        @Override +        public boolean isRedirected(final HttpRequest request, final HttpResponse response, +            final HttpContext context) throws ProtocolException { +          return false; +        } + +        @Override +        public HttpUriRequest getRedirect(final HttpRequest request, final HttpResponse response, +            final HttpContext context) throws ProtocolException { +          return null; +        } +      }; +    } + +    return httpClientBuilder.setRedirectStrategy(redirectStrategy).build(); + +  } + +  @PostConstruct +  private void initalize() { +    // initialize http client +    log.trace("Initializing HTTP Client-builder ... "); +    httpClientBuilder = HttpClients.custom(); + +    // set default request configuration +    final RequestConfig requestConfig = +        RequestConfig.custom() +            .setConnectTimeout( +                Integer.parseInt(basicConfig.getBasicConfiguration( +                    PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_CONNECTION, +                    DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_CONNECTION)) * 1000) +            .setConnectionRequestTimeout(Integer.parseInt(basicConfig.getBasicConfiguration( +                PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_REQUEST, +                DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_REQUEST)) * 1000) +            .setSocketTimeout(Integer.parseInt( +                basicConfig.getBasicConfiguration(PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_SOCKET, +                    DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_SOCKET)) +                * 1000) +            .build(); +    httpClientBuilder.setDefaultRequestConfig(requestConfig); + +    ClientAuthMode clientAuthMode = ClientAuthMode.fromString( +        basicConfig.getBasicConfiguration(PROP_CONFIG_CLIENT_MODE, ClientAuthMode.NONE.getMode())); +    if (clientAuthMode == null) { +      log.warn("Can Not parse ClientAuthMode! Set mode to default value"); +      clientAuthMode = ClientAuthMode.NONE; + +    } + +    // inject basic http authentication if required +    log.info("Client authentication-mode is set to: {}", clientAuthMode); +    injectBasicAuthenticationIfRequired(clientAuthMode); + +    // inject authentication if required +    final LayeredConnectionSocketFactory sslConnectionFactory = getSslContext(clientAuthMode); + +    // set pool connection if required +    injectConnectionPoolIfRequired(sslConnectionFactory); + + +  } + +  private void injectBasicAuthenticationIfRequired(final ClientAuthMode clientAuthMode) { +    if (clientAuthMode.equals(ClientAuthMode.PASSWORD)) { +      final CredentialsProvider provider = new BasicCredentialsProvider(); + +      final String username = +          basicConfig.getBasicConfiguration(PROP_CONFIG_CLIENT_AUTH_HTTP_USERNAME); +      final String password = +          basicConfig.getBasicConfiguration(PROP_CONFIG_CLIENT_AUTH_HTTP_PASSORD); + +      if (StringUtils.isEmpty(username)) { +        log.warn("Http basic authentication was activated but NOT username was set!"); + +      } + +      log.trace("Injecting basic authentication with username: {} and password: {}", username, +          password); +      final UsernamePasswordCredentials credentials = +          new UsernamePasswordCredentials(username, password); +      provider.setCredentials(AuthScope.ANY, credentials); +      httpClientBuilder.setDefaultCredentialsProvider(provider); +      log.info("Basic http authentication was injected with username: {}", username); + +    } else { +      log.trace("Injection of Http Basic authentication was skipped"); + +    } + +  } + +  private SSLContext buildSslContextWithSslClientAuthentication() +      throws KeyManagementException, UnrecoverableKeyException, NoSuchAlgorithmException, +      KeyStoreException, EaafConfigurationException { +    log.trace("Injecting SSL client-authentication into http client ... "); +    final KeyStore keystore = getSslAuthKeyStore(); +    final String keyPasswordString = +        basicConfig.getBasicConfiguration(PROP_CONFIG_CLIENT_AUTH_SSL_KEY_PASSWORD); +    log.trace("Open SSL Client-Auth keystore with password: {}", keyPasswordString); +    final char[] keyPassword = (keyPasswordString == null) ? StringUtils.EMPTY.toCharArray() +        : keyPasswordString.toCharArray(); +    return SSLContexts.custom().loadKeyMaterial(keystore, keyPassword).build(); + +  } + +  private KeyStore getSslAuthKeyStore() throws EaafConfigurationException { +    final KeyStoreType keyStoreType = KeyStoreType.fromString(basicConfig.getBasicConfiguration( +        PROP_CONFIG_CLIENT_AUTH_SSL_KEYSTORE_TYPE, KeyStoreType.PKCS12.getType())); +    final String localKeyStorePath = basicConfig +        .getBasicConfiguration(PROP_CONFIG_CLIENT_AUTH_SSL_KEYSTORE_PATH, StringUtils.EMPTY); +    final String keyStorePassword = basicConfig +        .getBasicConfiguration(PROP_CONFIG_CLIENT_AUTH_SSL_KEYSTORE_PASSORD, StringUtils.EMPTY); + +    try { +      log.debug("Open keyStore with type: {}", keyStoreType); +      KeyStore clientStore; +      if (keyStoreType.equals(KeyStoreType.PKCS12)) { +        clientStore = KeyStore.getInstance("pkcs12"); +      } else { +        clientStore = KeyStore.getInstance("JKS"); +      } + + +      log.debug("Read keyStore path: {} from configuration", localKeyStorePath); +      if (StringUtils.isNotEmpty(localKeyStorePath)) { +        final String absFilePath = FileUtils.makeAbsoluteUrl(localKeyStorePath, +            basicConfig.getConfigurationRootDirectory()); +        final Resource ressource = resourceLoader.getResource(absFilePath); +        final InputStream is = ressource.getInputStream(); +        log.trace("Load keyStore: {} with password: {}", absFilePath, keyStorePassword); +        clientStore.load(is, keyStorePassword.toCharArray()); +        is.close(); + +        return clientStore; + +      } else { +        log.warn("Path to keyStore for SSL Client-Authentication is empty or null"); +        throw new EaafConfigurationException( +            "Path to keyStore for SSL Client-Authentication is empty or null", new Object[] {}); + +      } + +    } catch (final KeyStoreException | NoSuchAlgorithmException | CertificateException +        | IOException e) { +      log.warn("Can NOT read keyStore: {} from filesystem", localKeyStorePath, null, e); +      throw new EaafConfigurationException("Can NOT read keyStore: {} from filesystem", +          new Object[] {localKeyStorePath}, e); + +    } + +  } + +  private LayeredConnectionSocketFactory getSslContext(final ClientAuthMode clientAuthMode) { +    SSLContext sslContext = null; +    try { +      if (clientAuthMode.equals(ClientAuthMode.SSL)) { +        sslContext = buildSslContextWithSslClientAuthentication(); + +      } else { +        log.trace("Initializing default SSL Context ... "); +        sslContext = SSLContext.getDefault(); + +      } + +      // set hostname verifier +      HostnameVerifier hostnameVerifier = null; +      if (basicConfig.getBasicConfigurationBoolean( +          PROP_CONFIG_CLIENT_HTTP_SSL_HOSTNAMEVERIFIER_TRUSTALL, false)) { +        hostnameVerifier = new NoopHostnameVerifier(); +        log.warn("HTTP client-builder deactivates SSL Host-name verification!"); + +      } + +      final LayeredConnectionSocketFactory sslSocketFactory = +          new SSLConnectionSocketFactory(sslContext, hostnameVerifier); + +      return sslSocketFactory; + +    } catch (final NoSuchAlgorithmException | KeyManagementException | UnrecoverableKeyException +        | KeyStoreException | EaafConfigurationException e) { +      log.warn("HTTP client-builder can NOT initialze SSL-Context", e); + +    } + +    log.info("HTTP client-builder successfuly initialized"); +    return null; + +  } + +  private void injectConnectionPoolIfRequired( +      final LayeredConnectionSocketFactory sslConnectionFactory) { +    if (basicConfig.getBasicConfigurationBoolean(PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_USE, +        true)) { +      PoolingHttpClientConnectionManager pool; + +      // set socketFactoryRegistry if SSLConnectionFactory is Set +      if (sslConnectionFactory != null) { +        final Registry<ConnectionSocketFactory> socketFactoryRegistry = +            RegistryBuilder.<ConnectionSocketFactory>create() +                .register("http", PlainConnectionSocketFactory.getSocketFactory()) +                .register("https", sslConnectionFactory).build(); +        log.trace("Inject SSLSocketFactory into pooled connection"); +        pool = new PoolingHttpClientConnectionManager(socketFactoryRegistry); + +      } else { +        pool = new PoolingHttpClientConnectionManager(); + +      } + +      pool.setDefaultMaxPerRoute(Integer.parseInt( +          basicConfig.getBasicConfiguration(PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXPERROUTE, +              DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXPERROUTE))); +      pool.setMaxTotal(Integer.parseInt( +          basicConfig.getBasicConfiguration(PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXTOTAL, +              DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXTOTAL))); + +      httpClientBuilder.setConnectionManager(pool); +      log.debug("Initalize http-client pool with, maxTotal: {} maxPerRoute: {}", pool.getMaxTotal(), +          pool.getDefaultMaxPerRoute()); + +    } else if (sslConnectionFactory != null) { +      log.trace("Inject SSLSocketFactory without connection pool"); +      httpClientBuilder.setSSLSocketFactory(sslConnectionFactory); + +    } + + +  } + + +  } diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HttpUtils.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HttpUtils.java new file mode 100644 index 00000000..394d2843 --- /dev/null +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HttpUtils.java @@ -0,0 +1,119 @@ +/* + * Copyright 2014 Federal Chancellery Austria MOA-ID has been developed in a cooperation between + * BRZ, the Federal Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + +package at.gv.egiz.eaaf.core.impl.utils; + +import javax.servlet.http.HttpServletRequest; +import org.apache.commons.lang3.StringUtils; + + + +public class HttpUtils { + + +  /** +   * Helper method to retrieve server URL including context path. +   * +   * @param request HttpServletRequest +   * @return Server URL including context path (e.g. http://localhost:8443/moa-id-auth +   */ +  public static String getBaseUrl(final HttpServletRequest request) { +    final StringBuffer buffer = new StringBuffer(getServerUrl(request)); + +    // add context path if available +    final String contextPath = request.getContextPath(); +    if (!StringUtils.isEmpty(contextPath)) { +      buffer.append(contextPath); +    } + +    return buffer.toString(); +  } + +  /** +   * Helper method to retrieve server URL. +   * +   * @param request HttpServletRequest +   * @return Server URL (e.g. http://localhost:8443) +   */ +  public static String getServerUrl(final HttpServletRequest request) { +    final StringBuffer buffer = new StringBuffer(); + +    // get protocol +    final String protocol = request.getScheme(); +    buffer.append(protocol).append("://"); + +    // server name +    buffer.append(request.getServerName()); + +    // add port if necessary +    final int port = request.getServerPort(); +    if ((protocol.equals("http") && port != 80) || (protocol.equals("https") && port != 443)) { +      buffer.append(':'); +      buffer.append(port); +    } + +    return buffer.toString(); +  } + +  /** +   * Extract the IDP PublicURLPrefix from authrequest. +   * +   * @param req HttpServletRequest +   * @return PublicURLPrefix which ends always without / +   */ +  public static String extractAuthUrlFromRequest(final HttpServletRequest req) { +    String authUrl = req.getScheme() + "://" + req.getServerName(); +    if ((req.getScheme().equalsIgnoreCase("https") && req.getServerPort() != 443) +        || (req.getScheme().equalsIgnoreCase("http") && req.getServerPort() != 80)) { +      authUrl = authUrl.concat(":" + req.getServerPort()); +    } +    authUrl = authUrl.concat(req.getContextPath()); +    return authUrl; + +  } + +  /** +   * Extract the IDP requested URL from authrequest. +   * +   * @param req HttpServletRequest +   * @return RequestURL which ends always without / +   */ +  public static String extractAuthServletPathFromRequest(final HttpServletRequest req) { +    return extractAuthUrlFromRequest(req).concat(req.getServletPath()); + +  } + +  /** +   * Add a http GET parameter to URL. +   * +   * @param url URL +   * @param paramname Name of the parameter. +   * @param paramvalue Value of the parameter. +   * @return +   */ +  public static String addUrlParameter(final String url, final String paramname, +      final String paramvalue) { +    final String param = paramname + "=" + paramvalue; +    if (url.indexOf("?") < 0) { +      return url + "?" + param; +    } else { +      return url + "&" + param; +    } +  } + +} diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/IHttpClientFactory.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/IHttpClientFactory.java index 1975fb52..0dc00573 100644 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/IHttpClientFactory.java +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/IHttpClientFactory.java @@ -4,18 +4,19 @@ import org.apache.http.impl.client.CloseableHttpClient;  public interface IHttpClientFactory { -	/** -	 * Return an instance of a Apache HTTP client that follows http redirects automatically -	 *  -	 * @return -	 */ -	CloseableHttpClient getHttpClient(); +  /** +   * Return an instance of a Apache HTTP client that follows http redirects automatically. +   * +   * @return +   */ +  CloseableHttpClient getHttpClient(); -	/** -	 * Return an instance of a Apache HTTP client -	 * @param followRedirects  -	 * @return -	 */ -	CloseableHttpClient getHttpClient(boolean followRedirects); -	 -}
\ No newline at end of file +  /** +   * Return an instance of a Apache HTTP client. +   * +   * @param followRedirects if <code>false</code>, the client does not flow 30x http redirects +   * @return +   */ +  CloseableHttpClient getHttpClient(boolean followRedirects); + +} diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/KeyStoreUtils.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/KeyStoreUtils.java index e3d74066..18ddf422 100644 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/KeyStoreUtils.java +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/KeyStoreUtils.java @@ -1,36 +1,28 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ,   - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.   * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at:   * https://joinup.ec.europa.eu/news/understanding-eupl-v12   * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - *   - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. + */ +  package at.gv.egiz.eaaf.core.impl.utils;  import java.io.BufferedInputStream;  import java.io.FileInputStream; -import java.io.FileNotFoundException;  import java.io.IOException;  import java.io.InputStream;  import java.net.URL; @@ -42,27 +34,27 @@ import java.security.cert.CertificateFactory;  /**   * Utility for creating and loading key stores. - *  + *   * @author Paul Ivancsics   * @version $Id$   */  public class KeyStoreUtils { -	 -	/** -	 * JAVA KeyStore -	 */ -	private static final String KEYSTORE_TYPE_JKS = "JKS"; -	 -	/** -	 * PKCS12 KeyStore -	 */ -	private static final String KEYSTORE_TYPE_PKCS12 = "PKCS12"; -	 -	 + +  /** +   * JAVA KeyStore. +   */ +  private static final String KEYSTORE_TYPE_JKS = "JKS"; + +  /** +   * PKCS12 KeyStore. +   */ +  private static final String KEYSTORE_TYPE_PKCS12 = "PKCS12"; + +    /**     * Loads a key store from file. -   *  +   *     * @param keystoreType key store type     * @param urlString URL of key store     * @param password password protecting the key store @@ -70,20 +62,35 @@ public class KeyStoreUtils {     * @throws IOException thrown while reading the key store from file     * @throws GeneralSecurityException thrown while creating the key store     */ -  public static KeyStore loadKeyStore( -    String keystoreType, -    String urlString, -    String password) -    throws IOException, GeneralSecurityException { - -    URL keystoreURL = new URL(urlString); -    InputStream in = keystoreURL.openStream(); +  public static KeyStore loadKeyStore(final String keystoreType, final String urlString, +      final String password) throws IOException, GeneralSecurityException { + +    final URL keystoreUrl = new URL(urlString); +    final InputStream in = keystoreUrl.openStream();      return loadKeyStore(keystoreType, in, password);    } +    /** -   * Loads a key store from an <code>InputStream</code>, and -   * closes the <code>InputStream</code>. -   *  +   * Load a KeyStore from Filesystem. +   * +   * @param keyStorePath Path to KeyStore +   * @param password KeyStore password +   * @return KeyStore +   * @throws KeyStoreException In case of a keystore error +   * @throws IOException In case of a general read error +   */ +  public static KeyStore loadKeyStore(final String keyStorePath, final String password) +      throws KeyStoreException, IOException { +    final URL keystoreUrl = new URL(keyStorePath); +    final InputStream in = keystoreUrl.openStream(); +    final InputStream isBuffered = new BufferedInputStream(in); +    return loadKeyStore(isBuffered, password); + +  } + +  /** +   * Loads a key store from an <code>InputStream</code>, and closes the <code>InputStream</code>. +   *     * @param keystoreType key store type     * @param in input stream     * @param password password protecting the key store @@ -91,39 +98,63 @@ public class KeyStoreUtils {     * @throws IOException thrown while reading the key store from the stream     * @throws GeneralSecurityException thrown while creating the key store     */ -  public static KeyStore loadKeyStore( -    String keystoreType, -    InputStream in, -    String password) -    throws IOException, GeneralSecurityException { +  public static KeyStore loadKeyStore(final String keystoreType, final InputStream in, +      final String password) throws IOException, GeneralSecurityException {      char[] chPassword = null; -    if (password != null) +    if (password != null) {        chPassword = password.toCharArray(); -    KeyStore ks = KeyStore.getInstance(keystoreType); +    } +    final KeyStore ks = KeyStore.getInstance(keystoreType);      ks.load(in, chPassword);      in.close();      return ks;    } +    /** -   * Creates a key store from X509 certificate files, aliasing them with -   * the index in the <code>String[]</code>, starting with <code>"0"</code>. -   *  +   * Loads a keyStore without knowing the keyStore type. +   * +   * @param is input stream +   * @param password Password protecting the keyStore +   * @return keyStore loaded +   * @throws KeyStoreException thrown if keyStore cannot be loaded +   * @throws IOException In case of a general error +   */ +  public static KeyStore loadKeyStore(final InputStream is, final String password) +      throws KeyStoreException, IOException { +    is.mark(1024 * 1024); +    KeyStore ks = null; +    try { +      try { +        ks = loadKeyStore(KEYSTORE_TYPE_PKCS12, is, password); +      } catch (final IOException e2) { +        is.reset(); +        ks = loadKeyStore(KEYSTORE_TYPE_JKS, is, password); +      } +    } catch (final Exception e) { +      e.printStackTrace(); + +    } +    return ks; + +  } + +  /** +   * Creates a key store from X509 certificate files, aliasing them with the index in the +   * <code>String[]</code>, starting with <code>"0"</code>. +   *     * @param keyStoreType key store type     * @param certFilenames certificate filenames     * @return key store created -   * @throws IOException thrown while reading the certificates from file -   * @throws GeneralSecurityException thrown while creating the key store +   * @throws Exception In case of an error     */ -  public static KeyStore createKeyStore( -    String keyStoreType, -    String[] certFilenames) -    throws IOException, GeneralSecurityException { +  public static KeyStore createKeyStore(final String keyStoreType, final String[] certFilenames) +      throws Exception { -    KeyStore ks = KeyStore.getInstance(keyStoreType); +    final KeyStore ks = KeyStore.getInstance(keyStoreType);      ks.load(null, null);      for (int i = 0; i < certFilenames.length; i++) { -      Certificate cert = loadCertificate(certFilenames[i]); +      final Certificate cert = loadCertificate(certFilenames[i]);        ks.setCertificateEntry("" + i, cert);      }      return ks; @@ -131,69 +162,36 @@ public class KeyStoreUtils {    /**     * Loads an X509 certificate from file. +   *     * @param certFilename filename     * @return the certificate loaded -   * @throws IOException thrown while reading the certificate from file -   * @throws GeneralSecurityException thrown while creating the certificate +   * @throws Exception In case of an IO exception     */ -  private static Certificate loadCertificate(String certFilename) -    throws IOException, GeneralSecurityException { +  private static Certificate loadCertificate(final String certFilename) +      throws Exception { +    FileInputStream in = null; +    try { +      in = new FileInputStream(certFilename); +      final CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); +      final Certificate cert = certFactory.generateCertificate(in); +      in.close(); +      return cert; -    FileInputStream in = new FileInputStream(certFilename); -    CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); -    Certificate cert = certFactory.generateCertificate(in); -    in.close(); -    return cert; +    } catch (final Exception e) { +      throw e; + +    } finally { +      if (in != null) { +        try { +          in.close(); +        } catch (final IOException e) { +          e.printStackTrace(); +        } + +      } +    }    } -   -  -	/** -	 * Loads a keyStore without knowing the keyStore type -	 * @param keyStorePath URL to the keyStore -	 * @param password Password protecting the keyStore -	 * @return keyStore loaded -	 * @throws KeyStoreException thrown if keyStore cannot be loaded -	 * @throws FileNotFoundException  -	 * @throws IOException  -	 */ -  public static KeyStore loadKeyStore(String keyStorePath, String password) throws KeyStoreException, IOException{ -		 -		//InputStream is = new FileInputStream(keyStorePath); -	  	URL keystoreURL = new URL(keyStorePath); -	    InputStream in = keystoreURL.openStream(); -		InputStream isBuffered = new BufferedInputStream(in);				 -		return loadKeyStore(isBuffered, password); -		 -	} -	 -	/** -	 * Loads a keyStore without knowing the keyStore type -	 * @param in input stream -	 * @param password Password protecting the keyStore -	 * @return keyStore loaded -	 * @throws KeyStoreException thrown if keyStore cannot be loaded -	 * @throws FileNotFoundException  -	 * @throws IOException  -	 */ -public static KeyStore loadKeyStore(InputStream is, String password) throws KeyStoreException, IOException{		 -		is.mark(1024*1024); -		KeyStore ks = null; -		try { -			try {				 -				ks = loadKeyStore(KEYSTORE_TYPE_PKCS12, is, password); -			} catch (IOException e2) { -				is.reset();				 -				ks = loadKeyStore(KEYSTORE_TYPE_JKS, is, password); -			} -		} catch(Exception e) {			 -			e.printStackTrace(); - -		} -		return ks;	 -						 -	} -   -	 +  } diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/KeyValueUtils.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/KeyValueUtils.java index e753f19f..929d2994 100644 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/KeyValueUtils.java +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/KeyValueUtils.java @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ,   - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.   * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at:   * https://joinup.ec.europa.eu/news/understanding-eupl-v12   * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - *   - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ +  package at.gv.egiz.eaaf.core.impl.utils;  import java.util.ArrayList; @@ -35,341 +28,347 @@ import java.util.Map;  import java.util.Map.Entry;  import java.util.Properties;  import java.util.Set; -  import javax.annotation.Nonnull;  import javax.annotation.Nullable; -  import org.apache.commons.lang3.StringUtils;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory;  /** + * Utils to operate on Key/Value based configurations. + *   * @author tlenz   *   */  public class KeyValueUtils { -	private static final Logger log = LoggerFactory.getLogger(KeyValueUtils.class); -	 -	public static final String KEY_DELIMITER = "."; -	public static final String CSV_DELIMITER = ","; -	public static final String KEYVVALUEDELIMITER = "="; -	public static final String DEFAULT_VALUE = "default"; -	 -	/** -	 * Convert Java properties into a Map<String, String> -	 * <br><br> -	 * <b>Important:</b> The key/values from properties must be of type String!  -	 *  -	 * @param properties -	 * @return -	 */ -	public static Map<String, String> convertPropertiesToMap(Properties properties) { -		return new HashMap<String, String>((Map) properties); -				 -		//INFO Java8 solution ;) -//				return properties.entrySet().stream().collect( -//			    Collectors.toMap( -//			            e -> e.getKey().toString(), -//			            e -> e.getValue().toString() -//			       ) -//			   ); -		 -	} -	 -	/** -	 * Extract the first child of an input key after a the prefix -	 *  -	 * @param key Full input key  -	 * @param prefix Prefix  -	 * @return Child key {String} if it exists or null -	 */ -	public static String getFirstChildAfterPrefix(String key, String prefix) {		 -		final String idAfterPrefix = removePrefixFromKey(key, prefix); -		if (idAfterPrefix != null) { -			final int index = idAfterPrefix.indexOf(KEY_DELIMITER); -			if (index > 0) { -				final String adding = idAfterPrefix.substring(0, index); -				if (!(adding.isEmpty())) { -					return adding; -					 -				} -			} else if (!(idAfterPrefix.isEmpty())) { -				return idAfterPrefix; -				 -			} -			 -		}					 -		return null; -	} -	 -	/** -	 * Extract the prefix from an input key -	 *  -	 * @param key Full input key -	 * @param suffix Suffix of this key -	 * @return Prefix {String} of the key or null if input key does not ends with postfix string  -	 */ -	public static String getPrefixFromKey(String key, String suffix) {			 -		if (key != null && suffix != null && key.endsWith(suffix)) { -			final String idPreforeSuffix = key.substring(0, key.length()-suffix.length());			 -			if (idPreforeSuffix.endsWith(KEY_DELIMITER)) -				return idPreforeSuffix.substring(0, idPreforeSuffix.length()-1); -			else -				return idPreforeSuffix; -		} -		return null; -		 -	} -	 -	/** -	 * Remove a prefix string from a key -	 *  -	 * @param key Full input key -	 * @param prefix Prefix, which should be removed -	 * @return The suffix of the input key or null if the input does not starts with the prefix -	 */ -	public static String removePrefixFromKey(String key, String prefix) { -		if (prefix == null) -			prefix = new String(); -		 -		if (key!=null && key.startsWith(prefix)) { -			String afterPrefix = key.substring(prefix.length());  -			final int index = afterPrefix.indexOf(KEY_DELIMITER); - -			if (index == 0) { -				afterPrefix = afterPrefix.substring(1); -				 -			} -			return afterPrefix; -			 -		}		 -		return null; -	} -	 -	/** -	 * Remove a prefix string from all keys in {Map<String, String>} of key/value pairs -	 *  -	 * @param keys Input data of key/value pairs -	 * @param prefix Prefix which should be removed -	 * @return {Map<String, String>} of key/value pairs without prefix in key, but never null -	 */ -	public static Map<String, String> removePrefixFromKeys(Map<String, String> keys, String prefix) { -		final Map<String, String> result = new HashMap<String, String>(); -		final Iterator<Entry<String, String>> interator = keys.entrySet().iterator(); -		while(interator.hasNext()) { -			final Entry<String, String> el = interator.next(); -			final String newKey = removePrefixFromKey(el.getKey(), prefix);			 -			if (StringUtils.isNotEmpty(newKey)) { -				result.put(newKey, el.getValue()); -			}			 -		} -		 -		return result; -	} - -	/** -	 * Get a subset of key/value pairs which starts with a prefix string -	 * The Prefix is removed from the key -	 *  -	 * @param keys Input data of key/value pairs -	 * @param prefix Prefix string -	 * @return {Map<String, String>} of key/value pairs without prefix in key, but never null -	 */ -	public static Map<String, String> getSubSetWithPrefix(Map<String, String> keys, String prefix) { -		return removePrefixFromKeys(keys, prefix); -	} -	 -	 -	/** -	 * Add a prefix to key/value pairs to make the key absolute according to key namespace convention -	 *  -	 * @param input Input key/value pairs which should be updated -	 * @param prefix Key prefix, which should be added if the key is not absolute -	 * @param absolutIdentifier Key identifier, which indicates an absolute key -	 * @return {Map<String, String>} of key/value pairs in which all keys are absolute but never null -	 */ -	public static Map<String, String> makeKeysAbsolut(Map<String, String> input, String prefix, String absolutIdentifier) { -		final Map<String, String> result = new HashMap<String, String>(); -		final Iterator<Entry<String, String>> interator = input.entrySet().iterator(); -		while(interator.hasNext()) { -			final Entry<String, String> el = interator.next(); -			if (!el.getKey().startsWith(absolutIdentifier)) { -				//key is not absolute -> add prefix -				result.put(prefix  -						+ KEY_DELIMITER -						+ el.getKey(),  -						el.getValue()); -								 -			} else { -				//key is absolute -				result.put(el.getKey(), el.getValue()); -			} -		} -		return result; -	} -	 -	/** -	 * Get the parent key string from an input key -	 *  -	 * @param key input key -	 * @return parent key or the empty String if no parent exists -	 */ -	public static String getParentKey(String key) { -		if (StringUtils.isNotEmpty(key)) { -			final int index = key.lastIndexOf(KEY_DELIMITER); -			if (index > 0) { -				return key.substring(0, index); -				 -			}			 -		} -		 -		return new String(); -	} - -	/** -	 * Find the highest free list counter -	 *  -	 * @param input Array of list keys -	 * @param listPrefix {String} prefix of the list -	 * @return {int} highest free list counter -	 */ -	public static int findNextFreeListCounter(String[] input, -			String listPrefix) { -		final List<Integer> counters = new ArrayList<Integer>(); -		if (input == null || input.length == 0) -			return 0; -		 -		else { -			for (final String key : input) { -				final String listIndex = getFirstChildAfterPrefix(key, listPrefix); -				counters.add(Integer.parseInt(listIndex)); -			 -			}		 -			Collections.sort(counters);		 -			return counters.get(counters.size()-1) + 1; -		} -	} - -	/** -	 * Find the highest free list counter -	 *  -	 * @param keySet {Set<String>} of list keys -	 * @param listPrefix {String} prefix of the list -	 * @return {int} highest free list counter -	 */ -	public static int findNextFreeListCounter(Set<String> keySet, -			String listPrefix) { -		if (keySet.isEmpty()) -			return 0; -		 -		final String[] array = new String[keySet.size()]; -		keySet.toArray(array); -		return findNextFreeListCounter(array, listPrefix); -	} -	 -	 -	/** -	 * Normalize a CSV encoded list of value of an key/value pair -	 *  -	 * This method removes all whitespace at the begin or the  -	 * end of CSV values and remove newLine signs at the end of value. -	 * The ',' is used as list delimiter -	 *  -	 * @param value CSV encoded input data -	 * @return normalized CSV encoded data or null if {value} is null or empty -	 */ -	public static String normalizeCSVValueString(String value) { -		String normalizedCodes = null; -		if (StringUtils.isNotEmpty(value)) {			 -			final String[] codes = value.split(CSV_DELIMITER); -			for (final String el: codes) { -				if (normalizedCodes == null) -					normalizedCodes = StringUtils.chomp(el.trim()); -				else -					normalizedCodes += "," + StringUtils.chomp(el.trim()); -				 -			} -		} -		return normalizedCodes; -	} -	 -	 -	/** -	 * Check a String if it is a comma separated list of values -	 *  -	 * This method uses the ',' as list delimiter. -	 *  -	 * @param value CSV encoded input data -	 * @return true if the input data contains a ',' and has more then 1 list element, otherwise false -	 */ -	public static boolean isCSVValueString(String value) { -		if (StringUtils.isNotEmpty(value)) {			 -			final String[] codes = value.split(CSV_DELIMITER); -			if (codes.length >= 2) { -				if (StringUtils.isNotEmpty(codes[1].trim())) -					return true; -				 -			}			 -		} -		 -		return false; -	} -	 -	/** -	 * Convert a CSV list to a List of CSV values -	 * <br><br> -	 * This method removes all whitespace at the begin or the  -	 * end of CSV values and remove newLine signs at the end of value. -	 * The ',' is used as list delimiter -	 *  -	 * @param csv CSV encoded input data -	 * @return List of CSV normalized values, but never null -	 */ -	@Nonnull -	public static List<String> getListOfCSVValues(@Nullable String csv) { -		final List<String> list = new ArrayList<String>(); -		if (StringUtils.isNotEmpty(csv)) {		 -			final String[] values = csv.split(CSV_DELIMITER); -			for (final String el: values) -				list.add(el.trim()); -		 -		} -		 -		return list; -	} -	 -	/** -	 * Convert a List of String elements to a Map of Key/Value pairs -	 * <br> -	 * Every List element used as a key/value pair and the '=' sign represents the delimiter between key and value  -	 *  -	 * @param elements List of key/value elements -	 * @return Map of Key / Value pairs, but never null -	 */ -	public static Map<String, String> convertListToMap(List<String> elements) { -		final Map<String, String> map = new HashMap<String, String>(); -		for (final String el : elements) { -			if (el.contains(KEYVVALUEDELIMITER)) { -				final String[] split = el.split(KEYVVALUEDELIMITER); -				map.put(split[0], split[1]); -				 -			} else -				log.debug("Key/Value Mapper: '" + el + "' contains NO '='. Ignore it."); -			 -		} -		 -		return map; -	} -	 -	/** -	 * This method remove all newline delimiter (\n or \r\n) from input data -	 *  -	 * @param value Input String -	 * @return Input String without newline characters -	 */ -	public static String removeAllNewlineFromString(String value) { -		return value.replaceAll("(\\t|\\r?\\n)+", ""); -		 -	} -	 +  private static final Logger log = LoggerFactory.getLogger(KeyValueUtils.class); + +  public static final String KEY_DELIMITER = "."; +  public static final String CSV_DELIMITER = ","; +  public static final String KEYVVALUEDELIMITER = "="; +  public static final String DEFAULT_VALUE = "default"; + +  /** +   * Convert Java properties into a Map String/String. +   * <br> +   * <b>Important:</b> The key/values from properties must be of type String! +   * +   * @param properties Java {@link Properties} that should be converted +   * @return +   */ +  public static Map<String, String> convertPropertiesToMap(final Properties properties) { +    return new HashMap<String, String>((Map) properties); + +    // INFO Java8 solution ;) +    // return properties.entrySet().stream().collect( +    // Collectors.toMap( +    // e -> e.getKey().toString(), +    // e -> e.getValue().toString() +    // ) +    // ); + +  } + +  /** +   * Extract the first child of an input key after a the prefix. +   * +   * @param key Full input key +   * @param prefix Prefix +   * @return Child key {String} if it exists or null +   */ +  public static String getFirstChildAfterPrefix(final String key, final String prefix) { +    final String idAfterPrefix = removePrefixFromKey(key, prefix); +    if (idAfterPrefix != null) { +      final int index = idAfterPrefix.indexOf(KEY_DELIMITER); +      if (index > 0) { +        final String adding = idAfterPrefix.substring(0, index); +        if (!(adding.isEmpty())) { +          return adding; + +        } +      } else if (!(idAfterPrefix.isEmpty())) { +        return idAfterPrefix; + +      } + +    } +    return null; +  } + +  /** +   * Extract the prefix from an input key. +   * +   * @param key Full input key +   * @param suffix Suffix of this key +   * @return Prefix {String} of the key or null if input key does not ends with postfix string +   */ +  public static String getPrefixFromKey(final String key, final String suffix) { +    if (key != null && suffix != null && key.endsWith(suffix)) { +      final String idPreforeSuffix = key.substring(0, key.length() - suffix.length()); +      if (idPreforeSuffix.endsWith(KEY_DELIMITER)) { +        return idPreforeSuffix.substring(0, idPreforeSuffix.length() - 1); +      } else { +        return idPreforeSuffix; +      } +    } +    return null; + +  } + +  /** +   * Remove a prefix string from a key. +   * +   * @param key Full input key +   * @param prefix Prefix, which should be removed +   * @return The suffix of the input key or null if the input does not starts with the prefix +   */ +  public static String removePrefixFromKey(final String key, String prefix) { +    if (prefix == null) { +      prefix = StringUtils.EMPTY; + +    } + +    if (key != null && key.startsWith(prefix)) { +      String afterPrefix = key.substring(prefix.length()); +      final int index = afterPrefix.indexOf(KEY_DELIMITER); + +      if (index == 0) { +        afterPrefix = afterPrefix.substring(1); + +      } +      return afterPrefix; + +    } +    return null; +  } + +  /** +   * Remove a prefix string from all keys in Map String/String of key/value pairs. +   * +   * @param keys Input data of key/value pairs +   * @param prefix Prefix which should be removed +   * @return Map String/String of key/value pairs without prefix in key, but never null +   */ +  public static Map<String, String> removePrefixFromKeys(final Map<String, String> keys, +      final String prefix) { +    final Map<String, String> result = new HashMap<>(); +    final Iterator<Entry<String, String>> interator = keys.entrySet().iterator(); +    while (interator.hasNext()) { +      final Entry<String, String> el = interator.next(); +      final String newKey = removePrefixFromKey(el.getKey(), prefix); +      if (StringUtils.isNotEmpty(newKey)) { +        result.put(newKey, el.getValue()); +      } +    } + +    return result; +  } + +  /** +   * Get a subset of key/value pairs which starts with a prefix string The Prefix is removed from +   * the key. +   * +   * @param keys Input data of key/value pairs +   * @param prefix Prefix string +   * @return Map String/String of key/value pairs without prefix in key, but never null +   */ +  public static Map<String, String> getSubSetWithPrefix(final Map<String, String> keys, +      final String prefix) { +    return removePrefixFromKeys(keys, prefix); +  } + + +  /** +   * Add a prefix to key/value pairs to make the key absolute according to key namespace convention. +   * +   * @param input Input key/value pairs which should be updated +   * @param prefix Key prefix, which should be added if the key is not absolute +   * @param absolutIdentifier Key identifier, which indicates an absolute key +   * @return Map String/String of key/value pairs in which all keys are absolute but never null +   */ +  public static Map<String, String> makeKeysAbsolut(final Map<String, String> input, +      final String prefix, final String absolutIdentifier) { +    final Map<String, String> result = new HashMap<>(); +    final Iterator<Entry<String, String>> interator = input.entrySet().iterator(); +    while (interator.hasNext()) { +      final Entry<String, String> el = interator.next(); +      if (!el.getKey().startsWith(absolutIdentifier)) { +        // key is not absolute -> add prefix +        result.put(prefix + KEY_DELIMITER + el.getKey(), el.getValue()); + +      } else { +        // key is absolute +        result.put(el.getKey(), el.getValue()); +      } +    } +    return result; +  } + +  /** +   * Get the parent key string from an input key. +   * +   * @param key input key +   * @return parent key or the empty String if no parent exists +   */ +  public static String getParentKey(final String key) { +    if (StringUtils.isNotEmpty(key)) { +      final int index = key.lastIndexOf(KEY_DELIMITER); +      if (index > 0) { +        return key.substring(0, index); + +      } +    } + +    return StringUtils.EMPTY; +  } + +  /** +   * Find the highest free list counter. +   * +   * @param input Array of list keys +   * @param listPrefix {String} prefix of the list +   * @return {int} highest free list counter +   */ +  public static int findNextFreeListCounter(final String[] input, final String listPrefix) { +    final List<Integer> counters = new ArrayList<>(); +    if (input == null || input.length == 0) { +      return 0; +    } else { +      for (final String key : input) { +        final String listIndex = getFirstChildAfterPrefix(key, listPrefix); +        counters.add(Integer.parseInt(listIndex)); + +      } +      Collections.sort(counters); +      return counters.get(counters.size() - 1) + 1; +    } +  } + +  /** +   * Find the highest free list counter. +   * +   * @param keySet Set of list keys +   * @param listPrefix {String} prefix of the list +   * @return {int} highest free list counter +   */ +  public static int findNextFreeListCounter(final Set<String> keySet, final String listPrefix) { +    if (keySet.isEmpty()) { +      return 0; +    } + +    final String[] array = new String[keySet.size()]; +    keySet.toArray(array); +    return findNextFreeListCounter(array, listPrefix); +  } + + +  /** +   * Normalize a CSV encoded list of value of an key/value pair. +   * +   * <p> +   * This method removes all whitespace at the begin or the end of CSV values and remove newLine +   * signs at the end of value. The ',' is used as list delimiter +   * </p> +   * +   * @param value CSV encoded input data +   * @return normalized CSV encoded data or null if {value} is null or empty +   */ +  public static String normalizeCsvValueString(final String value) { +    String normalizedCodes = null; +    if (StringUtils.isNotEmpty(value)) { +      final String[] codes = value.split(CSV_DELIMITER); +      for (final String el : codes) { +        if (normalizedCodes == null) { +          normalizedCodes = StringUtils.chomp(el.trim()); +        } else { +          normalizedCodes += "," + StringUtils.chomp(el.trim()); +        } + +      } +    } +    return normalizedCodes; +  } + + +  /** +   * Check a String if it is a comma separated list of values. +   * +   * <p> +   * This method uses the ',' as list delimiter. +   * </p> +   * +   * @param value CSV encoded input data +   * @return true if the input data contains a ',' and has more then 1 list element, otherwise false +   */ +  public static boolean isCsvValueString(final String value) { +    if (StringUtils.isNotEmpty(value)) { +      final String[] codes = value.split(CSV_DELIMITER); +      if (codes.length >= 2 +          && StringUtils.isNotEmpty(codes[1].trim())) { +        return true; + +      } +    } + +    return false; +  } + +  /** +   * Convert a CSV list to a List of CSV values. <br> +   * <br> +   * This method removes all whitespace at the begin or the end of CSV values and remove newLine +   * signs at the end of value. The ',' is used as list delimiter +   * +   * @param csv CSV encoded input data +   * @return List of CSV normalized values, but never null +   */ +  @Nonnull +  public static List<String> getListOfCsvValues(@Nullable final String csv) { +    final List<String> list = new ArrayList<>(); +    if (StringUtils.isNotEmpty(csv)) { +      final String[] values = csv.split(CSV_DELIMITER); +      for (final String el : values) { +        list.add(el.trim()); +      } + +    } + +    return list; +  } + +  /** +   * Convert a List of String elements to a Map of Key/Value pairs. <br> +   * Every List element used as a key/value pair and the '=' sign represents the delimiter between +   * key and value +   * +   * @param elements List of key/value elements +   * @return Map of Key / Value pairs, but never null +   */ +  public static Map<String, String> convertListToMap(final List<String> elements) { +    final Map<String, String> map = new HashMap<>(); +    for (final String el : elements) { +      if (el.contains(KEYVVALUEDELIMITER)) { +        final String[] split = el.split(KEYVVALUEDELIMITER); +        map.put(split[0], split[1]); + +      } else { +        log.debug("Key/Value Mapper: '" + el + "' contains NO '='. Ignore it."); +      } + +    } + +    return map; +  } + +  /** +   * This method remove all newline delimiter (\n or \r\n) from input data. +   * +   * @param value Input String +   * @return Input String without newline characters +   */ +  public static String removeAllNewlineFromString(final String value) { +    return value.replaceAll("(\\t|\\r?\\n)+", ""); + +  } +  } diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/NodeIteratorAdapter.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/NodeIteratorAdapter.java index ec57b92a..755c4431 100644 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/NodeIteratorAdapter.java +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/NodeIteratorAdapter.java @@ -1,92 +1,79 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ,   - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.   * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at:   * https://joinup.ec.europa.eu/news/understanding-eupl-v12   * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - *   - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ +  package at.gv.egiz.eaaf.core.impl.utils;  import java.util.ListIterator; -  import org.w3c.dom.DOMException;  import org.w3c.dom.Node;  import org.w3c.dom.traversal.NodeFilter;  import org.w3c.dom.traversal.NodeIterator;  /** - * A <code>NodeIterator</code> implementation based on a - * <code>ListIterator</code>. - *  + * A <code>NodeIterator</code> implementation based on a <code>ListIterator</code>. + *   * @see java.util.ListIterator   * @see org.w3c.dom.traversal.NodeIterator - *  + *   */  public class NodeIteratorAdapter implements NodeIterator {    /** The <code>ListIterator</code> to wrap. */ -  private ListIterator nodeIterator; +  private final ListIterator nodeIterator;    /**     * Create a new <code>NodeIteratorAdapter</code>. +   *     * @param nodeIterator The <code>ListIterator</code> to iterate over.     */ -  public NodeIteratorAdapter(ListIterator nodeIterator) { +  public NodeIteratorAdapter(final ListIterator nodeIterator) {      this.nodeIterator = nodeIterator;    } -  /** -   * @see org.w3c.dom.traversal.NodeIterator#getRoot() -   */ + +  @Override    public Node getRoot() {      return null;    } -  /** -   * @see org.w3c.dom.traversal.NodeIterator#getWhatToShow() -   */ + +  @Override    public int getWhatToShow() {      return NodeFilter.SHOW_ALL;    } -  /** -   * @see org.w3c.dom.traversal.NodeIterator#getFilter() -   */ + +  @Override    public NodeFilter getFilter() {      return null;    } -  /** -   * @see org.w3c.dom.traversal.NodeIterator#getExpandEntityReferences() -   */ + +  @Override    public boolean getExpandEntityReferences() {      return false;    } -  /** -   * @see org.w3c.dom.traversal.NodeIterator#nextNode() -   */ + +  @Override    public Node nextNode() throws DOMException {      if (nodeIterator.hasNext()) {        return (Node) nodeIterator.next(); @@ -94,9 +81,8 @@ public class NodeIteratorAdapter implements NodeIterator {      return null;    } -  /** -   * @see org.w3c.dom.traversal.NodeIterator#previousNode() -   */ + +  @Override    public Node previousNode() throws DOMException {      if (nodeIterator.hasPrevious()) {        return (Node) nodeIterator.previous(); @@ -104,10 +90,10 @@ public class NodeIteratorAdapter implements NodeIterator {      return null;    } -  /** -   * @see org.w3c.dom.traversal.NodeIterator#detach() -   */ + +  @Override    public void detach() { +    }  } diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/NodeListAdapter.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/NodeListAdapter.java index 69045aaa..a942f75e 100644 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/NodeListAdapter.java +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/NodeListAdapter.java @@ -1,68 +1,58 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ,   - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.   * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at:   * https://joinup.ec.europa.eu/news/understanding-eupl-v12   * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - *   - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ +  package at.gv.egiz.eaaf.core.impl.utils;  import java.util.List; -  import org.w3c.dom.Node;  import org.w3c.dom.NodeList;  /**   * A <code>NodeList</code> implementation based on a <code>List</code>. - *  + *   * @see java.util.List   * @see org.w3c.dom.NodeList   */  public class NodeListAdapter implements NodeList {    /** The <code>List</code> to wrap. */ -  private List nodeList; -   +  private final List nodeList; +    /**     * Create a new <code>NodeListAdapter</code>. -   *  -   * @param nodeList The <code>List</code> containing the nodes.  +   * +   * @param nodeList The <code>List</code> containing the nodes.     */ -  public NodeListAdapter(List nodeList) { +  public NodeListAdapter(final List nodeList) {      this.nodeList = nodeList;    } -  /** -   * @see org.w3c.dom.NodeList#item(int) -   */ -  public Node item(int index) { + +  @Override +  public Node item(final int index) {      return (Node) nodeList.get(index);    } -  /** -   * @see org.w3c.dom.NodeList#getLength() -   */ + +  @Override    public int getLength() {      return nodeList.size();    } diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/Random.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/Random.java index e236b3a9..14d54b0b 100644 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/Random.java +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/Random.java @@ -1,176 +1,188 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ,   - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.   * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at:   * https://joinup.ec.europa.eu/news/understanding-eupl-v12   * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - *   - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. + */  package at.gv.egiz.eaaf.core.impl.utils; +import java.io.UnsupportedEncodingException;  import java.nio.ByteBuffer;  import java.security.NoSuchAlgorithmException;  import java.security.SecureRandom;  import java.text.DateFormat;  import java.text.SimpleDateFormat;  import java.util.Date; - +import at.gv.egiz.eaaf.core.impl.idp.process.support.SecureRandomHolder;  import org.apache.commons.codec.binary.Hex;  import org.apache.commons.lang3.ArrayUtils;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory; -import at.gv.egiz.eaaf.core.impl.idp.process.support.SecureRandomHolder; -  /** - * Random number generator used to generate ID's + * Random number generator used to generate ID's. + *   * @author Paul Ivancsics   * @version $Id$   */  public class Random { -	private static final Logger log = LoggerFactory.getLogger(Random.class); -	 -	private final static char[] allowedPreFix =  -		{'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z', -		 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'}; -	private static final DateFormat dateFormater = new SimpleDateFormat("yyyyddMM"); -	 -  /** random number generator used */ -	private static SecureRandom random; -	//private static SeedGenerator seedgenerator;	 -		 -	static { -		try { -			random = SecureRandom.getInstance("SHA256PRNG-FIPS186"); -			 -		} catch (NoSuchAlgorithmException e) { -			log.warn("Can NOT initialize SecureRandom with: 'SHA256PRNG-FIPS186'. Use 'StrongSecureRandom' as backup"); -			random = SecureRandomHolder.getInstance(); -			 -		} -		 -		 -		//random = iaik.security.random.SHA256FIPS186Random.getDefault();		 -	} -	 -	/** -	 * Generate a unique process reference-value [160bit], which always starts with a letter -	 * <br> -	 * This unique ID consists of single letter, a 64bit date String[yyyyddMM], -	 *  and a 88bit random value.   -	 *  -	 * @return 160bit ID, which is hex encoded -	 */ -	public static String nextProcessReferenceValue() {		 -		//pre-process all three parts of a unique reference value -		String now = dateFormater.format(new Date()); //8 bytes = 64bit -		byte[] randValue = nextByteRandom(11); -		char preFix = allowedPreFix[Math.abs(random.nextInt() % allowedPreFix.length)]; -	  -		//generate ID -		String returnValue = preFix + new String(Hex.encodeHex(ArrayUtils.addAll(now.getBytes(), randValue))); // 20 bytes = 160 bits -		if (returnValue.length() > 40) -			return returnValue.substring(0, 40); -		else -			return returnValue; -			 -	} -	 -	 -	 -	/** -	 * Creates a new random number [256bit], and encode it as hex value. -	 *  -	 * @return random hex encoded value [256bit] -	 */ -	public static String nextHexRandom32() { -		return new String(Hex.encodeHex(nextByteRandom(32))); // 32 bytes = 256 bits -		 -	} -	 -	/** -	 * Creates a new random number [128bit], and encode it as hex value. -	 *  -	 * @return random hex encoded value [128bit] -	 */ -	public static String nextHexRandom16() { -		return new String(Hex.encodeHex(nextByteRandom(16))); // 16 bytes = 128 bits -		 -	} -	 -	  /** -	   * Creates a new random number [64bit], to be used as an ID. -	   *  -	   * @return random long as a String [64bit] -	   */ -	public static String nextLongRandom() {	   -		return "".concat(String.valueOf(Math.abs(generateLongRandom(32)))); // 32 bytes = 256 bits	 -			 -	  } -		 +  private static final Logger log = LoggerFactory.getLogger(Random.class); + +  private static final char[] allowedPreFix = +      {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', +          's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', +          'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}; + +  /** random number generator used. */ +  private static SecureRandom random; +  // private static SeedGenerator seedgenerator; + +  static { +    try { +      random = SecureRandom.getInstance("SHA256PRNG-FIPS186"); + +    } catch (final NoSuchAlgorithmException e) { +      log.warn( +          "Can NOT initialize SecureRandom with: 'SHA256PRNG-FIPS186'. Use 'StrongSecureRandom' as backup"); +      random = SecureRandomHolder.getInstance(); + +    } + + +    // random = iaik.security.random.SHA256FIPS186Random.getDefault(); +  } + +  /** +   * Generate a unique process reference-value [160bit], which always starts with a letter <br> +   * This unique ID consists of single letter, a 64bit date String[yyyyddMM], and a 88bit random +   * value. +   * +   * @return 160bit ID, which is hex encoded +   */ +  public static String nextProcessReferenceValue() { +    // pre-process all three parts of a unique reference value +    final DateFormat dateFormater = new SimpleDateFormat("yyyyddMM"); +    final String now = dateFormater.format(new Date()); // 8 bytes = 64bit +    final byte[] randValue = nextByteRandom(11); +    final char preFix = allowedPreFix[Math.abs(random.nextInt() % allowedPreFix.length)]; + +    // generate ID +    String returnValue; +    try { +      returnValue = preFix + new String(Hex.encodeHex(ArrayUtils.addAll(now.getBytes("UTF-8"), randValue))); + +      // 20 bytes = 160 bits +      if (returnValue.length() > 40) { +        return returnValue.substring(0, 40); +      } else { +        return returnValue; +      } + +    } catch (final UnsupportedEncodingException e) { +      throw new RuntimeException(e); + +    } + + + +  } + + + +  /** +   * Creates a new random number [256bit], and encode it as hex value. +   * +   * @return random hex encoded value [256bit] +   */ +  public static String nextHexRandom32() { +    return new String(Hex.encodeHex(nextByteRandom(32))); // 32 bytes = 256 bits + +  } + +  /** +   * Creates a new random number [128bit], and encode it as hex value. +   * +   * @return random hex encoded value [128bit] +   */ +  public static String nextHexRandom16() { +    return new String(Hex.encodeHex(nextByteRandom(16))); // 16 bytes = 128 bits + +  } + +  /** +   * Creates a new random number [64bit], to be used as an ID. +   * +   * @return random long as a String [64bit] +   */ +  public static String nextLongRandom() { +    return "".concat(String.valueOf(Math.abs(generateLongRandom(32)))); // 32 bytes = 256 bits + +  } +    /**     * Creates a new random number, to be used as an ID. -   *  +   *     * @return random long as a String [64bit]     */ -	@Deprecated -  public static String nextRandom() {	   -	long l = ByteBuffer.wrap(nextByteRandom(32)).getLong(); // 32 bytes = 256 bits -	return "" + Math.abs(l); -		 +  @Deprecated +  public static String nextRandom() { +    final long l = ByteBuffer.wrap(nextByteRandom(32)).getLong(); // 32 bytes = 256 bits +    return "" + Math.abs(l); +    } -   -/** - * Creates a new random byte[] - * 	 - * @param size Size of random number in byte - * @return - */ -public static byte[] nextBytes(int size) { -	return  nextByteRandom(size); -	 -} -   + +  /** +   * Creates a new random byte[]. +   * +   * @param size Size of random number in byte +   * @return +   */ +  public static byte[] nextBytes(final int size) { +    return nextByteRandom(size); + +  } + +  /** +   * initialize random-number generator. +   */    public static void seedRandom() { -	  //TODO: implement reflection on IAIK Seed generator	   -//      seedgenerator = iaik.security.random.AutoSeedGenerator.getDefault();   -//	  if (seedgenerator.seedAvailable()) -//		  random.setSeed(seedgenerator.getSeed()); -	   -	  random.setSeed(System.nanoTime()); +    // TODO: implement reflection on IAIK Seed generator +    // seedgenerator = iaik.security.random.AutoSeedGenerator.getDefault(); +    // if (seedgenerator.seedAvailable()) +    // random.setSeed(seedgenerator.getSeed()); + +    random.setSeed(System.nanoTime());    } -   -	private static long generateLongRandom(int size) { -		return ByteBuffer.wrap(nextByteRandom(size)).getLong(); 	 -	} -   + +  private static long generateLongRandom(final int size) { +    return ByteBuffer.wrap(nextByteRandom(size)).getLong(); +  } +    /** -   * Generate a new random number -   *  +   * Generate a new random number. +   *     * @param size Size of random number in byte     * @return     */ -  private static synchronized byte[] nextByteRandom(int size) { -	  byte[] b = new byte[size]; -	  random.nextBytes(b);			  -	  return b; -	   +  private static synchronized byte[] nextByteRandom(final int size) { +    final byte[] b = new byte[size]; +    random.nextBytes(b); +    return b; +    }  } diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SecurePendingRequestIdGenerationStrategy.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SecurePendingRequestIdGenerationStrategy.java index f0ef9b38..ee88c4bb 100644 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SecurePendingRequestIdGenerationStrategy.java +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SecurePendingRequestIdGenerationStrategy.java @@ -1,19 +1,24 @@  package at.gv.egiz.eaaf.core.impl.utils;  import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset;  import java.security.InvalidKeyException;  import java.security.NoSuchAlgorithmException;  import java.security.spec.InvalidKeySpecException;  import java.security.spec.KeySpec;  import java.util.Arrays;  import java.util.Base64; -  import javax.annotation.PostConstruct;  import javax.crypto.Mac;  import javax.crypto.SecretKey;  import javax.crypto.SecretKeyFactory;  import javax.crypto.spec.PBEKeySpec; - +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.api.utils.IPendingRequestIdGenerationStrategy; +import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.exceptions.EaafIllegalStateException; +import at.gv.egiz.eaaf.core.exceptions.PendingReqIdValidationException;  import org.apache.commons.lang3.StringUtils;  import org.joda.time.DateTime;  import org.joda.time.DurationFieldType; @@ -25,190 +30,209 @@ import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.lang.NonNull;  import org.springframework.lang.Nullable; -import at.gv.egiz.eaaf.core.api.idp.IConfiguration; -import at.gv.egiz.eaaf.core.api.utils.IPendingRequestIdGenerationStrategy; -import at.gv.egiz.eaaf.core.exceptions.EAAFConfigurationException; -import at.gv.egiz.eaaf.core.exceptions.EAAFException; -import at.gv.egiz.eaaf.core.exceptions.EAAFIllegalStateException; -import at.gv.egiz.eaaf.core.exceptions.PendingReqIdValidationException; -  /** - * PendingRequestId generation strategy based on signed tokens that facilitates extended token validation - *  + * PendingRequestId generation strategy based on signed tokens that facilitates extended token + * validation. + *   * @author tlenz   *   */ -public class SecurePendingRequestIdGenerationStrategy implements IPendingRequestIdGenerationStrategy { -	private static final Logger log = LoggerFactory.getLogger(SecurePendingRequestIdGenerationStrategy.class); -	 -	@Autowired(required=true) IConfiguration baseConfig; -	 -	public static final String CONFIG_PROP_PENDINGREQUESTID_DIGIST_SECRET = "core.pendingrequestid.digist.secret"; -	public static final String CONFIG_PROP_PENDINGREQUESTID_DIGIST_ALGORITHM = "core.pendingrequestid.digist.algorithm"; -	public static final String CONFIG_PROP_PENDINGREQUESTID_MAX_LIFETIME = "core.pendingrequestid.maxlifetime"; -	 -	public static final String DEFAULT_PENDINGREQUESTID_DIGIST_ALGORITHM = "HmacSHA256"; -	public static final String DEFAULT_PENDINGREQUESTID_MAX_LIFETIME = "300"; -	 -	private static final int ENCODED_TOKEN_PARTS = 3; -	private static final String TOKEN_SEPARATOR = "|"; -	private static final DateTimeFormatter TOKEN_TEXTUAL_DATE_FORMAT = -            DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss SSS"); -		 -	private int maxPendingRequestIdLifeTime = 300; -	private final int maxPendingReqIdSize = 1024; -	private String digistAlgorithm = null; -	private SecretKey key = null; -	private final byte[] salt = "notRequiredInThisScenario".getBytes(); -		 -	@Override -	public String generateExternalPendingRequestId() throws EAAFException { -		try { -			final String toSign = buildInternalToken(Random.nextLongRandom(), DateTime.now()); -			final StringBuilder externalPendingRequestId= new StringBuilder(); -			externalPendingRequestId.append(toSign); -			externalPendingRequestId.append(TOKEN_SEPARATOR); -			externalPendingRequestId.append(Base64.getEncoder().encodeToString(calculateHMAC(toSign)));									 -			return Base64.getUrlEncoder().encodeToString(externalPendingRequestId.toString().getBytes("UTF-8")); -			 -		} catch (final UnsupportedEncodingException e) { -			throw new EAAFException("internal.99", new Object[] {e.getMessage()}, e); -			 -		} -		 -	} - -	@Override -	public String getPendingRequestIdWithOutChecks(String externalPendingReqId) throws PendingReqIdValidationException { -		final String[] tokenElements = extractTokens(externalPendingReqId); -		return tokenElements[1]; -		 -	} -	 -	@Override -	public String validateAndGetPendingRequestId(String externalPendingReqId) throws PendingReqIdValidationException {				 -		try { -			final String[] tokenElements = extractTokens(externalPendingReqId);						 -			final String internalPendingReqId = tokenElements[1]; -			final DateTime timeStamp = TOKEN_TEXTUAL_DATE_FORMAT.parseDateTime(tokenElements[0]); -							 -			log.trace("Checking HMAC from externalPendingReqId ... "); -			final byte[] tokenDigest = Base64.getDecoder().decode(tokenElements[2]); -			final byte[] refDigist = calculateHMAC(buildInternalToken(internalPendingReqId, timeStamp)); -			if (!Arrays.equals(tokenDigest, refDigist)) { -				log.warn("Digest of Token does NOT match"); -				log.debug("Token: {} | Ref: {}", tokenDigest, refDigist); -				throw new  PendingReqIdValidationException(null, "Digest of pendingRequestId does NOT match"); -			 -			}				 -			log.debug("PendingRequestId HMAC digest check successful"); -					 -			log.trace("Checking valid period ... "); -			final DateTime now = DateTime.now(); -			if (timeStamp.withFieldAdded( -					DurationFieldType.seconds(), maxPendingRequestIdLifeTime).isBefore(now)) { -				log.warn("Token exceeds the valid period"); -				log.debug("Token: {} | Now: {}", timeStamp, now ); -				throw new PendingReqIdValidationException(internalPendingReqId, "PendingRequestId exceeds the valid period"); -			 -			} -			log.debug("Token valid-period check successful"); -		 -			return internalPendingReqId; -				 -			 -		} catch (final IllegalArgumentException | EAAFIllegalStateException e) {				 -			log.warn("Token is NOT a valid String. Msg: {}", e.getMessage()); -			log.debug("TokenValue: {}", externalPendingReqId); -			throw new PendingReqIdValidationException(null, "PendingReqId is NOT a valid String", e); -		 -		}    -	} -	 -	@NonNull -	private String[] extractTokens(@Nullable String externalPendingReqId) throws PendingReqIdValidationException { -		if (StringUtils.isEmpty(externalPendingReqId)) { -			log.info("PendingReqId is 'null' or empty"); -			throw new PendingReqIdValidationException(null, "PendingReqId is 'null' or empty"); -			 -		} -		 -		log.trace("RAW external pendingReqId: {}", externalPendingReqId); -		final byte[] externalPendingReqIdBytes = Base64.getUrlDecoder().decode(externalPendingReqId); -		 -		if (externalPendingReqIdBytes.length > maxPendingReqIdSize) { -			log.warn("pendingReqId size exceeds {}", maxPendingReqIdSize); -			throw new PendingReqIdValidationException(null, "pendingReqId exceeds max.size: " + maxPendingReqIdSize); -			 -		} -		 -		final String stringToken = new String(externalPendingReqIdBytes); -		if (StringUtils.countMatches(stringToken, TOKEN_SEPARATOR) == ENCODED_TOKEN_PARTS - 1) { -			final String[] tokenElements = StringUtils.split(stringToken,  -					TOKEN_SEPARATOR, ENCODED_TOKEN_PARTS); -			return tokenElements; -			 -		} else { -			log.warn("PendingRequestId has an unvalid format"); -			log.debug("PendingRequestId: {}", stringToken);				 -			throw new PendingReqIdValidationException(null, "PendingReqId has an unvalid format"); -			 -		} -						 -	} -	 -	 -	@PostConstruct -	private void initialize() throws EAAFConfigurationException { -		log.debug("Initializing " + this.getClass().getName() + " ... "); -		 -		final String pendingReqIdDigistSecret = baseConfig.getBasicConfiguration(CONFIG_PROP_PENDINGREQUESTID_DIGIST_SECRET); -		if (StringUtils.isEmpty(pendingReqIdDigistSecret)) -			throw new EAAFConfigurationException("config.08", new Object[] {CONFIG_PROP_PENDINGREQUESTID_DIGIST_SECRET}); -		 -		digistAlgorithm = baseConfig.getBasicConfiguration(CONFIG_PROP_PENDINGREQUESTID_DIGIST_ALGORITHM, DEFAULT_PENDINGREQUESTID_DIGIST_ALGORITHM);				 -		 -		maxPendingRequestIdLifeTime = Integer.valueOf( -				baseConfig.getBasicConfiguration(CONFIG_PROP_PENDINGREQUESTID_MAX_LIFETIME, DEFAULT_PENDINGREQUESTID_MAX_LIFETIME)); -		 -		try { -			final SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WITHHMACSHA256"); -			final KeySpec spec = new PBEKeySpec(pendingReqIdDigistSecret.toCharArray(), salt, 10000, 128); -			key = keyFactory.generateSecret(spec); -			 -			 -		} catch (NoSuchAlgorithmException | InvalidKeySpecException e) { -			log.error("Can NOT initialize TokenService with configuration object", e); -			throw new EAAFConfigurationException("config.09",  -					new Object[] {	CONFIG_PROP_PENDINGREQUESTID_DIGIST_SECRET,  -									"Can NOT generate HMAC key"},  -						e); -			 -		} -		 -		log.info(this.getClass().getName() + " initialized with digistAlg: {} and maxLifeTime: {}", digistAlgorithm, maxPendingRequestIdLifeTime); -		 -	} -	 -	private String buildInternalToken(String internalPendingReqId, DateTime now) { -		return new StringBuilder() -				.append(TOKEN_TEXTUAL_DATE_FORMAT.print(now)) -				.append(TOKEN_SEPARATOR) -				.append(internalPendingReqId).toString();   -	} -	 -	private byte[] calculateHMAC(String toSign) throws EAAFIllegalStateException { -		try {			 -			final Mac mac = Mac.getInstance(digistAlgorithm); -			mac.init(key); -			return mac.doFinal(toSign.getBytes("UTF-8")); -			 -		} catch (UnsupportedEncodingException | NoSuchAlgorithmException | InvalidKeyException e) { -			log.error("Can NOT generate secure pendingRequestId", e); -			throw new EAAFIllegalStateException(new Object[] {"Can NOT caluclate digist for secure pendingRequestId"}, e); -			 -		} -		 -	} +public class SecurePendingRequestIdGenerationStrategy +    implements IPendingRequestIdGenerationStrategy { +  private static final Logger log = +      LoggerFactory.getLogger(SecurePendingRequestIdGenerationStrategy.class); + +  @Autowired(required = true) +  IConfiguration baseConfig; + +  public static final String CONFIG_PROP_PENDINGREQUESTID_DIGIST_SECRET = +      "core.pendingrequestid.digist.secret"; +  public static final String CONFIG_PROP_PENDINGREQUESTID_DIGIST_ALGORITHM = +      "core.pendingrequestid.digist.algorithm"; +  public static final String CONFIG_PROP_PENDINGREQUESTID_MAX_LIFETIME = +      "core.pendingrequestid.maxlifetime"; + +  public static final String DEFAULT_PENDINGREQUESTID_DIGIST_ALGORITHM = "HmacSHA256"; +  public static final String DEFAULT_PENDINGREQUESTID_MAX_LIFETIME = "300"; + +  private static final int ENCODED_TOKEN_PARTS = 3; +  private static final String TOKEN_SEPARATOR = "|"; +  private static final DateTimeFormatter TOKEN_TEXTUAL_DATE_FORMAT = +      DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss SSS"); + +  private int maxPendingRequestIdLifeTime = 300; +  private final int maxPendingReqIdSize = 1024; +  private String digistAlgorithm = null; +  private SecretKey key = null; +  private final byte[] salt = "notRequiredInThisScenario".getBytes(Charset.defaultCharset()); + +  @Override +  public String generateExternalPendingRequestId() throws EaafException { +    try { +      final String toSign = buildInternalToken(Random.nextLongRandom(), DateTime.now()); +      final StringBuilder externalPendingRequestId = new StringBuilder(); +      externalPendingRequestId.append(toSign); +      externalPendingRequestId.append(TOKEN_SEPARATOR); +      externalPendingRequestId.append(Base64.getEncoder().encodeToString(calculateHmac(toSign))); +      return Base64.getUrlEncoder() +          .encodeToString(externalPendingRequestId.toString().getBytes("UTF-8")); + +    } catch (final UnsupportedEncodingException e) { +      throw new EaafException("internal.99", new Object[] {e.getMessage()}, e); + +    } + +  } + +  @Override +  public String getPendingRequestIdWithOutChecks(final String externalPendingReqId) +      throws PendingReqIdValidationException { +    try { +      final String[] tokenElements = extractTokens(externalPendingReqId); +      return tokenElements[1]; + +    } catch (final UnsupportedEncodingException e) { +      throw new RuntimeException(e); + +    } +  } + +  @Override +  public String validateAndGetPendingRequestId(final String externalPendingReqId) +      throws PendingReqIdValidationException { +    try { +      final String[] tokenElements = extractTokens(externalPendingReqId); +      final String internalPendingReqId = tokenElements[1]; +      final DateTime timeStamp = TOKEN_TEXTUAL_DATE_FORMAT.parseDateTime(tokenElements[0]); + +      log.trace("Checking HMAC from externalPendingReqId ... "); +      final byte[] tokenDigest = Base64.getDecoder().decode(tokenElements[2]); +      final byte[] refDigist = calculateHmac(buildInternalToken(internalPendingReqId, timeStamp)); +      if (!Arrays.equals(tokenDigest, refDigist)) { +        log.warn("Digest of Token does NOT match"); +        log.debug("Token: {} | Ref: {}", tokenDigest, refDigist); +        throw new PendingReqIdValidationException(null, +            "Digest of pendingRequestId does NOT match"); + +      } +      log.debug("PendingRequestId HMAC digest check successful"); + +      log.trace("Checking valid period ... "); +      final DateTime now = DateTime.now(); +      if (timeStamp.withFieldAdded(DurationFieldType.seconds(), maxPendingRequestIdLifeTime) +          .isBefore(now)) { +        log.warn("Token exceeds the valid period"); +        log.debug("Token: {} | Now: {}", timeStamp, now); +        throw new PendingReqIdValidationException(internalPendingReqId, +            "PendingRequestId exceeds the valid period"); + +      } +      log.debug("Token valid-period check successful"); + +      return internalPendingReqId; + + +    } catch (final IllegalArgumentException | EaafIllegalStateException e) { +      log.warn("Token is NOT a valid String. Msg: {}", e.getMessage()); +      log.debug("TokenValue: {}", externalPendingReqId); +      throw new PendingReqIdValidationException(null, "PendingReqId is NOT a valid String", e); + +    } catch (final UnsupportedEncodingException e) { +      throw new RuntimeException(e); + +    } +  } + +  @NonNull +  private String[] extractTokens(@Nullable final String externalPendingReqId) +      throws PendingReqIdValidationException, UnsupportedEncodingException { +    if (StringUtils.isEmpty(externalPendingReqId)) { +      log.info("PendingReqId is 'null' or empty"); +      throw new PendingReqIdValidationException(null, "PendingReqId is 'null' or empty"); + +    } + +    log.trace("RAW external pendingReqId: {}", externalPendingReqId); +    final byte[] externalPendingReqIdBytes = Base64.getUrlDecoder().decode(externalPendingReqId); + +    if (externalPendingReqIdBytes.length > maxPendingReqIdSize) { +      log.warn("pendingReqId size exceeds {}", maxPendingReqIdSize); +      throw new PendingReqIdValidationException(null, +          "pendingReqId exceeds max.size: " + maxPendingReqIdSize); + +    } + +    final String stringToken = new String(externalPendingReqIdBytes, "UTF-8"); +    if (StringUtils.countMatches(stringToken, TOKEN_SEPARATOR) == ENCODED_TOKEN_PARTS - 1) { +      final String[] tokenElements = +          StringUtils.split(stringToken, TOKEN_SEPARATOR, ENCODED_TOKEN_PARTS); +      return tokenElements; + +    } else { +      log.warn("PendingRequestId has an unvalid format"); +      log.debug("PendingRequestId: {}", stringToken); +      throw new PendingReqIdValidationException(null, "PendingReqId has an unvalid format"); + +    } + +  } + + +  @PostConstruct +  private void initialize() throws EaafConfigurationException { +    log.debug("Initializing " + this.getClass().getName() + " ... "); + +    final String pendingReqIdDigistSecret = +        baseConfig.getBasicConfiguration(CONFIG_PROP_PENDINGREQUESTID_DIGIST_SECRET); +    if (StringUtils.isEmpty(pendingReqIdDigistSecret)) { +      throw new EaafConfigurationException("config.08", +          new Object[] {CONFIG_PROP_PENDINGREQUESTID_DIGIST_SECRET}); +    } + +    digistAlgorithm = baseConfig.getBasicConfiguration( +        CONFIG_PROP_PENDINGREQUESTID_DIGIST_ALGORITHM, DEFAULT_PENDINGREQUESTID_DIGIST_ALGORITHM); + +    maxPendingRequestIdLifeTime = +        Integer.parseInt(baseConfig.getBasicConfiguration(CONFIG_PROP_PENDINGREQUESTID_MAX_LIFETIME, +            DEFAULT_PENDINGREQUESTID_MAX_LIFETIME)); + +    try { +      final SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WITHHMACSHA256"); +      final KeySpec spec = new PBEKeySpec(pendingReqIdDigistSecret.toCharArray(), salt, 10000, 128); +      key = keyFactory.generateSecret(spec); + + +    } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { +      log.error("Can NOT initialize TokenService with configuration object", e); +      throw new EaafConfigurationException("config.09", +          new Object[] {CONFIG_PROP_PENDINGREQUESTID_DIGIST_SECRET, "Can NOT generate HMAC key"}, +          e); + +    } + +    log.info(this.getClass().getName() + " initialized with digistAlg: {} and maxLifeTime: {}", +        digistAlgorithm, maxPendingRequestIdLifeTime); + +  } + +  private String buildInternalToken(final String internalPendingReqId, final DateTime now) { +    return new StringBuilder().append(TOKEN_TEXTUAL_DATE_FORMAT.print(now)).append(TOKEN_SEPARATOR) +        .append(internalPendingReqId).toString(); +  } + +  private byte[] calculateHmac(final String toSign) throws EaafIllegalStateException { +    try { +      final Mac mac = Mac.getInstance(digistAlgorithm); +      mac.init(key); +      return mac.doFinal(toSign.getBytes("UTF-8")); + +    } catch (UnsupportedEncodingException | NoSuchAlgorithmException | InvalidKeyException e) { +      log.error("Can NOT generate secure pendingRequestId", e); +      throw new EaafIllegalStateException( +          new Object[] {"Can NOT caluclate digist for secure pendingRequestId"}, e); + +    } + +  }  } diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/ServletUtils.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/ServletUtils.java index 38e873e2..0d16e9cd 100644 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/ServletUtils.java +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/ServletUtils.java @@ -1,43 +1,41 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ,   - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.   * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at:   * https://joinup.ec.europa.eu/news/understanding-eupl-v12   * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - *   - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. + */  package at.gv.egiz.eaaf.core.impl.utils;  import javax.servlet.http.HttpServletRequest;  public class ServletUtils { -   -	 -  public static String getBaseUrl( HttpServletRequest request ) { -	    if ( ( request.getServerPort() == 80 ) || -	         ( request.getServerPort() == 443 ) ) -	      return request.getScheme() + "://" + -	             request.getServerName() + -	             request.getContextPath(); -	    else -	      return request.getScheme() + "://" + -	             request.getServerName() + ":" + request.getServerPort() + -	             request.getContextPath(); -	  } -   + +  /** +   * Get Context URL from http request. +   * +   * @param request http Request +   * @return Context URL +   */ +  public static String getBaseUrl(final HttpServletRequest request) { +    if ((request.getServerPort() == 80) || (request.getServerPort() == 443)) { +      return request.getScheme() + "://" + request.getServerName() + request.getContextPath(); +    } else { +      return request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() +          + request.getContextPath(); +    } +  } +  } diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SimplePendingRequestIdGenerationStrategy.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SimplePendingRequestIdGenerationStrategy.java index 6b8fe9b7..049f7175 100644 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SimplePendingRequestIdGenerationStrategy.java +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SimplePendingRequestIdGenerationStrategy.java @@ -1,38 +1,42 @@  package at.gv.egiz.eaaf.core.impl.utils; -import org.apache.commons.lang3.StringUtils; -  import at.gv.egiz.eaaf.core.api.utils.IPendingRequestIdGenerationStrategy;  import at.gv.egiz.eaaf.core.exceptions.PendingReqIdValidationException; +import org.apache.commons.lang3.StringUtils;  /** - * Simple pendingRequestId generation strategy that facilitates no extended validation - *  + * Simple pendingRequestId generation strategy that facilitates no extended validation. + *   * @author tlenz   *   */ -public class SimplePendingRequestIdGenerationStrategy implements IPendingRequestIdGenerationStrategy { - -	@Override -	public String generateExternalPendingRequestId() { -		return Random.nextLongRandom(); -		 -	} - -	@Override -	public String validateAndGetPendingRequestId(String pendingReqId) throws PendingReqIdValidationException { -		return getPendingRequestIdWithOutChecks(pendingReqId); -				 -	} - -	@Override -	public String getPendingRequestIdWithOutChecks(String externalPendingReqId) throws PendingReqIdValidationException { -		if (StringUtils.isEmpty(externalPendingReqId)) -			throw new PendingReqIdValidationException(externalPendingReqId, "PendingRequestId is empty or null"); -		 -		 -		 -		return externalPendingReqId; -	} +public class SimplePendingRequestIdGenerationStrategy +    implements IPendingRequestIdGenerationStrategy { + +  @Override +  public String generateExternalPendingRequestId() { +    return Random.nextLongRandom(); + +  } + +  @Override +  public String validateAndGetPendingRequestId(final String pendingReqId) +      throws PendingReqIdValidationException { +    return getPendingRequestIdWithOutChecks(pendingReqId); + +  } + +  @Override +  public String getPendingRequestIdWithOutChecks(final String externalPendingReqId) +      throws PendingReqIdValidationException { +    if (StringUtils.isEmpty(externalPendingReqId)) { +      throw new PendingReqIdValidationException(externalPendingReqId, +          "PendingRequestId is empty or null"); +    } + + + +    return externalPendingReqId; +  }  } diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/StreamUtils.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/StreamUtils.java index 530da777..cc784870 100644 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/StreamUtils.java +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/StreamUtils.java @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ,   - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.   * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at:   * https://joinup.ec.europa.eu/news/understanding-eupl-v12   * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - *   - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. + */ +  package at.gv.egiz.eaaf.core.impl.utils; @@ -32,38 +25,37 @@ import java.io.ByteArrayOutputStream;  import java.io.IOException;  import java.io.InputStream;  import java.io.OutputStream; -import java.io.PrintStream;  /**   * Utility methods for streams. - *  + *   * @author Patrick Peck   * @version $Id$   */  public class StreamUtils { -   +    /**     * Compare the contents of two <code>InputStream</code>s. -   *  +   *     * @param is1 The 1st <code>InputStream</code> to compare.     * @param is2 The 2nd <code>InputStream</code> to compare. -   * @return boolean <code>true</code>, if both streams contain the exactly the -   * same content, <code>false</code> otherwise. +   * @return boolean <code>true</code>, if both streams contain the exactly the same content, +   *         <code>false</code> otherwise.     * @throws IOException An error occurred reading one of the streams.     */ -  public static boolean compareStreams(InputStream is1, InputStream is2)  -    throws IOException { -       -    byte[] buf1 = new byte[256]; -    byte[] buf2 = new byte[256]; +  public static boolean compareStreams(final InputStream is1, final InputStream is2) +      throws IOException { + +    final byte[] buf1 = new byte[256]; +    final byte[] buf2 = new byte[256];      int length1;      int length2; -   +      try {        while (true) {          length1 = is1.read(buf1);          length2 = is2.read(buf2); -         +          if (length1 != length2) {            return false;          } @@ -74,128 +66,125 @@ public class StreamUtils {            return false;          }        } -    } catch (IOException e) { +    } catch (final IOException e) {        throw e;      } finally {        // close both streams        try {          is1.close();          is2.close(); -      } catch (IOException e) { -        // ignore this +      } catch (final IOException e) { +        e.printStackTrace(); +        }      }    } -   +    /**     * Compare two byte arrays, up to a given maximum length. -   *  +   *     * @param b1 1st byte array to compare.     * @param b2 2nd byte array to compare.     * @param length The maximum number of bytes to compare. -   * @return <code>true</code>, if the byte arrays are equal, <code>false</code> -   * otherwise. +   * @return <code>true</code>, if the byte arrays are equal, <code>false</code> otherwise.     */ -  private static boolean compareBytes(byte[] b1, byte[] b2, int length) { +  private static boolean compareBytes(final byte[] b1, final byte[] b2, final int length) {      if (b1.length != b2.length) {        return false;      } -   +      for (int i = 0; i < b1.length && i < length; i++) {        if (b1[i] != b2[i]) {          return false;        }      } -   +      return true;    }    /**     * Reads a byte array from a stream. +   *     * @param in The <code>InputStream</code> to read.     * @return The bytes contained in the given <code>InputStream</code>.     * @throws IOException on any exception thrown     */ -  public static byte[] readStream(InputStream in) throws IOException { +  public static byte[] readStream(final InputStream in) throws IOException { -    ByteArrayOutputStream out = new ByteArrayOutputStream(); +    final ByteArrayOutputStream out = new ByteArrayOutputStream();      copyStream(in, out, null); -		   -		/*   -    ByteArrayOutputStream out = new ByteArrayOutputStream(); -    int b; -    while ((b = in.read()) >= 0) -      out.write(b); -     -    */ + +    /* +     * ByteArrayOutputStream out = new ByteArrayOutputStream(); int b; while ((b = in.read()) >= 0) +     * out.write(b); +     * +     */      in.close();      return out.toByteArray();    }    /**     * Reads a <code>String</code> from a stream, using given encoding. +   *     * @param in The <code>InputStream</code> to read. -   * @param encoding The character encoding to use for converting the bytes -   * of the <code>InputStream</code> into a <code>String</code>. -   * @return The content of the given <code>InputStream</code> converted into -   * a <code>String</code>. +   * @param encoding The character encoding to use for converting the bytes of the +   *        <code>InputStream</code> into a <code>String</code>. +   * @return The content of the given <code>InputStream</code> converted into a <code>String</code>.     * @throws IOException on any exception thrown     */ -  public static String readStream(InputStream in, String encoding) throws IOException { -    ByteArrayOutputStream out = new ByteArrayOutputStream(); +  public static String readStream(final InputStream in, final String encoding) throws IOException { +    final ByteArrayOutputStream out = new ByteArrayOutputStream();      copyStream(in, out, null);      /* -    ByteArrayOutputStream out = new ByteArrayOutputStream(); -    int b; -    while ((b = in.read()) >= 0) -      out.write(b); -      */ +     * ByteArrayOutputStream out = new ByteArrayOutputStream(); int b; while ((b = in.read()) >= 0) +     * out.write(b); +     */      in.close();      return out.toString(encoding);    } -   +    /** -   * Reads all data (until EOF is reached) from the given source to the  -   * destination stream. If the destination stream is null, all data is dropped. -   * It uses the given buffer to read data and forward it. If the buffer is  -   * null, this method allocates a buffer. +   * Reads all data (until EOF is reached) from the given source to the destination stream. If the +   * destination stream is null, all data is dropped. It uses the given buffer to read data and +   * forward it. If the buffer is null, this method allocates a buffer.     *     * @param source The stream providing the data. -   * @param destination The stream that takes the data. If this is null, all -   *                    data from source will be read and discarded. -   * @param buffer The buffer to use for forwarding. If it is null, the method -   *               allocates a buffer. -   * @exception IOException If reading from the source or writing to the  -   *                        destination fails. +   * @param destination The stream that takes the data. If this is null, all data from source will +   *        be read and discarded. +   * @param buffer The buffer to use for forwarding. If it is null, the method allocates a buffer. +   * @exception IOException If reading from the source or writing to the destination fails.     */ -  private static void copyStream(InputStream source, OutputStream destination, byte[] buffer) throws IOException { +  private static void copyStream(final InputStream source, final OutputStream destination, +      byte[] buffer) throws IOException {      if (source == null) {        throw new NullPointerException("Argument \"source\" must not be null.");      }      if (buffer == null) {        buffer = new byte[8192];      } -     +      if (destination != null) {        int bytesRead;        while ((bytesRead = source.read(buffer)) >= 0) {          destination.write(buffer, 0, bytesRead);        }      } else { -      while (source.read(buffer) >= 0); -    }     -  } -   -  /** -   * Gets the stack trace of the <code>Throwable</code> passed in as a string. -   * @param t The <code>Throwable</code>. -   * @return a String representing the stack trace of the <code>Throwable</code>. -   */ -  public static String getStackTraceAsString(Throwable t) -  { -    ByteArrayOutputStream stackTraceBIS = new ByteArrayOutputStream(); -    t.printStackTrace(new PrintStream(stackTraceBIS)); -    return new String(stackTraceBIS.toByteArray()); +      while (source.read(buffer) >= 0) { +         +      } +    }    } + +  // /** +  // * Gets the stack trace of the <code>Throwable</code> passed in as a string. +  // * +  // * @param t The <code>Throwable</code>. +  // * @return a String representing the stack trace of the <code>Throwable</code>. +  // */ +  // public static String getStackTraceAsString(final Throwable t) { +  // final ByteArrayOutputStream stackTraceBis = new ByteArrayOutputStream(); +  // t.printStackTrace(new PrintStream(stackTraceBis)); +  // return new String(stackTraceBis.toByteArray()); +  // }  } diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/TransactionIDUtils.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/TransactionIDUtils.java deleted file mode 100644 index 2e016848..00000000 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/TransactionIDUtils.java +++ /dev/null @@ -1,101 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ,   - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - *   - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.core.impl.utils; - - -import at.gv.egiz.eaaf.core.api.IRequest; - -/** - * @author tlenz - * - */ -public class TransactionIDUtils { - -	  //MDC variables for logging -	  public static final String MDC_TRANSACTION_ID = "transactionId"; -	  public static final String MDC_SESSION_ID = "sessionId"; -	  public static final String MDC_SERVICEPROVIDER_ID = "oaId"; -	 -	/** -	 * Set all MDC variables from pending request to this threat context<br> -	 * These includes SessionID, TransactionID, and unique service-provider identifier -	 *  -	 * @param pendingRequest -	 */ -	public static void setAllLoggingVariables(IRequest pendingRequest) { -		setTransactionId(pendingRequest.getUniqueTransactionIdentifier()); -		setSessionId(pendingRequest.getUniqueSessionIdentifier()); -		setServiceProviderId(pendingRequest.getServiceProviderConfiguration().getUniqueIdentifier()); -		 -	} -	 -	/** -	 * Remove all MDC variables from this threat context -	 *  -	 */ -	public static void removeAllLoggingVariables() { -		removeSessionId(); -		removeTransactionId(); -		removeServiceProviderId(); -		 -	} -	 -	 -	public static void setServiceProviderId(String oaUniqueId) {		 -		org.slf4j.MDC.put(MDC_SERVICEPROVIDER_ID, oaUniqueId); -		 -	} -	 -	public static void removeServiceProviderId() { -		org.slf4j.MDC.remove(MDC_SERVICEPROVIDER_ID); -		 -	} -	 -	public static void setTransactionId(String pendingRequestID) {	    -		org.slf4j.MDC.put(MDC_TRANSACTION_ID,  -				"TID-" + pendingRequestID); -				     -	} -		 -	public static void removeTransactionId() { -		org.slf4j.MDC.remove(MDC_TRANSACTION_ID); -		 -	} -		 -	public static void setSessionId(String uniqueSessionId) {	  	 -		org.slf4j.MDC.put(MDC_SESSION_ID,  -				"SID-" + uniqueSessionId); -				     -	} -		 -	public static void removeSessionId() { -		org.slf4j.MDC.remove(MDC_SESSION_ID); -		 -	} -	 -	 -} diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/TransactionIdUtils.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/TransactionIdUtils.java new file mode 100644 index 00000000..3875e587 --- /dev/null +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/TransactionIdUtils.java @@ -0,0 +1,94 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + +package at.gv.egiz.eaaf.core.impl.utils; + + +import at.gv.egiz.eaaf.core.api.IRequest; + +/** + * Transaction Identifier Utils. + * + * @author tlenz + * + */ +public class TransactionIdUtils { + +  // MDC variables for logging +  public static final String MDC_TRANSACTION_ID = "transactionId"; +  public static final String MDC_SESSION_ID = "sessionId"; +  public static final String MDC_SERVICEPROVIDER_ID = "oaId"; + +  /** +   * Set all MDC variables from pending request to this threat context.<br> +   * These includes SessionID, TransactionID, and unique service-provider identifier +   * +   * @param pendingRequest Http request object +   */ +  public static void setAllLoggingVariables(final IRequest pendingRequest) { +    setTransactionId(pendingRequest.getUniqueTransactionIdentifier()); +    setSessionId(pendingRequest.getUniqueSessionIdentifier()); +    setServiceProviderId(pendingRequest.getServiceProviderConfiguration().getUniqueIdentifier()); + +  } + +  /** +   * Remove all MDC variables from this threat context. +   * +   */ +  public static void removeAllLoggingVariables() { +    removeSessionId(); +    removeTransactionId(); +    removeServiceProviderId(); + +  } + + +  public static void setServiceProviderId(final String oaUniqueId) { +    org.slf4j.MDC.put(MDC_SERVICEPROVIDER_ID, oaUniqueId); + +  } + +  public static void removeServiceProviderId() { +    org.slf4j.MDC.remove(MDC_SERVICEPROVIDER_ID); + +  } + +  public static void setTransactionId(final String pendingRequestID) { +    org.slf4j.MDC.put(MDC_TRANSACTION_ID, "TID-" + pendingRequestID); + +  } + +  public static void removeTransactionId() { +    org.slf4j.MDC.remove(MDC_TRANSACTION_ID); + +  } + +  public static void setSessionId(final String uniqueSessionId) { +    org.slf4j.MDC.put(MDC_SESSION_ID, "SID-" + uniqueSessionId); + +  } + +  public static void removeSessionId() { +    org.slf4j.MDC.remove(MDC_SESSION_ID); + +  } + + +} diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/X509Utils.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/X509Utils.java index b3fb42c4..00a31a13 100644 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/X509Utils.java +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/X509Utils.java @@ -7,56 +7,45 @@ import javax.security.auth.x500.X500Principal;  public class X509Utils { -	  /** -	   * Sorts the Certificate Chain by IssuerDN and SubjectDN. The [0]-Element should be the Hostname, -	   * the last Element should be the Root Certificate. -	   *  -	   * @param certs -	   *          The first element must be the correct one. -	   * @return sorted Certificate Chain -	   */ -	  public static List<X509Certificate> sortCertificates( -		      List<X509Certificate> certs) -		  { -		    int length = certs.size(); -		    if (certs.size() <= 1) -		    { -		      return certs; -		    } +  /** +   * Sorts the Certificate Chain by IssuerDN and SubjectDN. The [0]-Element should be the Hostname, +   * the last Element should be the Root Certificate. +   *  +   * @param certs The first element must be the correct one. +   * @return sorted Certificate Chain +   */ +  public static List<X509Certificate> sortCertificates(final List<X509Certificate> certs) { +    final int length = certs.size(); +    if (certs.size() <= 1) { +      return certs; +    } -		    for (X509Certificate cert : certs) -		    { -		      if (cert == null) -		      { -		        throw new NullPointerException(); -		      } -		    } +    for (final X509Certificate cert : certs) { +      if (cert == null) { +        throw new NullPointerException(); +      } +    } -		    for (int i = 0; i < length; i++) -		    { -		      boolean found = false; -		      X500Principal issuer = certs.get(i).getIssuerX500Principal(); -		      for (int j = i + 1; j < length; j++) -		      { -		        X500Principal subject = certs.get(j).getSubjectX500Principal(); -		        if (issuer.equals(subject)) -		        { -		          // sorting necessary? -		          if (i + 1 != j) -		          { -		            X509Certificate tmp = certs.get(i + 1); -		            certs.set(i + 1, certs.get(j)); -		            certs.set(j, tmp); -		          } -		          found = true; -		        } -		      } -		      if (!found) -		      { -		        break; -		      } -		    } +    for (int i = 0; i < length; i++) { +      boolean found = false; +      final X500Principal issuer = certs.get(i).getIssuerX500Principal(); +      for (int j = i + 1; j < length; j++) { +        final X500Principal subject = certs.get(j).getSubjectX500Principal(); +        if (issuer.equals(subject)) { +          // sorting necessary? +          if (i + 1 != j) { +            final X509Certificate tmp = certs.get(i + 1); +            certs.set(i + 1, certs.get(j)); +            certs.set(j, tmp); +          } +          found = true; +        } +      } +      if (!found) { +        break; +      } +    } -		    return certs; -		} +    return certs; +  }  } | 
