Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.directory.fortress.core.rest; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; import java.util.Enumeration; import java.util.List; import java.util.Properties; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.IOUtils; import org.apache.directory.fortress.core.GlobalErrIds; import org.apache.directory.fortress.core.RestException; import org.apache.directory.fortress.core.model.FortRequest; import org.apache.directory.fortress.core.model.FortResponse; import org.apache.directory.fortress.core.model.ObjectFactory; import org.apache.directory.fortress.core.model.Props; import org.apache.directory.fortress.core.util.Config; import org.apache.directory.fortress.core.util.EncryptUtil; import org.apache.http.HttpEntity; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.CredentialsProvider; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.client.HttpClientBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This utility class provides methods that wrap Apache's HTTP Client APIs. This class is thread safe. * * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> */ public final class RestUtils { private static final String CLS_NM = RestUtils.class.getName(); private static final Logger LOG = LoggerFactory.getLogger(CLS_NM); private static final String HTTP_PW_PROP = "http.pw"; private static final int HTTP_OK = 200; private static final int HTTP_401_UNAUTHORIZED = 401; private static final int HTTP_403_FORBIDDEN = 403; private static final int HTTP_404_NOT_FOUND = 404; private static CachedJaxbContext cachedJaxbContext = new CachedJaxbContext(); // static member contains this private static volatile RestUtils sINSTANCE = null; /** * Used to manage trust store properties. If enabled, create SSL connection. * */ private String trustStore; private String trustStorePw; // These members contain the http coordinates to a running fortress-rest instance: private String httpUid, httpPw, httpHost, httpPort, httpProtocol, fortressRestVersion, serviceName, uri; /** * create a new request and set its tenant id. * @param szContextId contains the tenant id * @return a brand new FortRequest */ static FortRequest getRequest(String szContextId) { FortRequest request = new FortRequest(); request.setContextId(szContextId); return request; } public static RestUtils getInstance() { if (sINSTANCE == null) { synchronized (RestUtils.class) { if (sINSTANCE == null) { sINSTANCE = new RestUtils(); } } } return sINSTANCE; } private void init() { httpUid = Config.getInstance().getProperty("http.user"); httpPw = ((EncryptUtil.isEnabled()) ? EncryptUtil.getInstance().decrypt(Config.getInstance().getProperty(HTTP_PW_PROP)) : Config.getInstance().getProperty(HTTP_PW_PROP)); httpHost = Config.getInstance().getProperty("http.host"); httpPort = Config.getInstance().getProperty("http.port"); httpProtocol = Config.getInstance().getProperty("http.protocol", "http"); trustStore = Config.getInstance().getProperty("trust.store"); trustStorePw = Config.getInstance().getProperty("trust.store.password"); fortressRestVersion = System.getProperty("version"); serviceName = "fortress-rest-" + fortressRestVersion; uri = httpProtocol + "://" + httpHost + ":" + httpPort + "/" + serviceName + "/"; LOG.info("Set JSSE truststore properties:"); LOG.info("javax.net.ssl.trustStore: {}", trustStore); System.setProperty("javax.net.ssl.trustStore", trustStore); System.setProperty("javax.net.ssl.trustStorePassword", trustStorePw); } private RestUtils() { init(); } /** * Marshall the request into an XML String. * * @param request * @return String containing xml request * @throws RestException */ public static String marshal(FortRequest request) throws RestException { String szRetValue; try { // Create a JAXB context passing in the class of the object we want to marshal/unmarshal final JAXBContext context = cachedJaxbContext.getJaxbContext(FortRequest.class); // ============================================================================================================= // Marshalling OBJECT to XML // ============================================================================================================= // Create the marshaller, that will transform the object into XML final Marshaller marshaller = context.createMarshaller(); // Create a stringWriter to hold the XML final StringWriter stringWriter = new StringWriter(); // Marshal the javaObject and write the XML to the stringWriter marshaller.marshal(request, stringWriter); szRetValue = stringWriter.toString(); } catch (JAXBException je) { String error = "marshal caught JAXBException=" + je; throw new RestException(GlobalErrIds.REST_MARSHALL_ERR, error, je); } return szRetValue; } /** * Unmarshall the XML response into its associated Java objects. * * @param szResponse * @return FortResponse * @throws RestException */ public static FortResponse unmarshall(String szResponse) throws RestException { FortResponse response; try { // Create a JAXB context passing in the class of the object we want to marshal/unmarshal final JAXBContext context = cachedJaxbContext.getJaxbContext(FortResponse.class); // Create the unmarshaller, that will transform the XML back into an object final Unmarshaller unmarshaller = context.createUnmarshaller(); response = (FortResponse) unmarshaller.unmarshal(new StringReader(szResponse)); } catch (JAXBException je) { String error = "unmarshall caught JAXBException=" + je; throw new RestException(GlobalErrIds.REST_UNMARSHALL_ERR, error, je); } return response; } /** * Perform HTTP Get REST request. * * @param userId * @param password * @param id * @param id2 * @param id3 * @param function * @return String containing response * @throws RestException */ public String get(String userId, String password, String id, String id2, String id3, String function) throws RestException { String url = uri + function + "/" + id; if (id2 != null) { url += "/" + id2; } if (id3 != null) { url += "/" + id3; } LOG.debug("get function1:{}, id1:{}, id2:{}, id3:{}, url:{}", function, id, id2, id3, url); HttpGet get = new HttpGet(url); setMethodHeaders(get); return handleHttpMethod(get, HttpClientBuilder.create() .setDefaultCredentialsProvider(getCredentialProvider(userId, password)).build()); } /** * Perform HTTP Get REST request. * * @param id * @param id2 * @param id3 * @param function * @return String containing response * @throws RestException */ public String get(String id, String id2, String id3, String function) throws RestException { return get(null, null, id, id2, id3, function); } /** * Perform an HTTP Post REST operation. * * @param userId * @param password * @param szInput * @param function * @return String containing response * @throws RestException */ public String post(String userId, String password, String szInput, String function) throws RestException { LOG.debug("post uri=[{}], function=[{}], request=[{}]", uri, function, szInput); String szResponse = null; HttpPost post = new HttpPost(uri + function); post.addHeader("Accept", "text/xml"); setMethodHeaders(post); try { HttpEntity entity = new StringEntity(szInput, ContentType.TEXT_XML); post.setEntity(entity); org.apache.http.client.HttpClient httpclient = HttpClientBuilder.create() .setDefaultCredentialsProvider(getCredentialProvider(userId, password)).build(); HttpResponse response = httpclient.execute(post); String error; switch (response.getStatusLine().getStatusCode()) { case HTTP_OK: szResponse = IOUtils.toString(response.getEntity().getContent(), "UTF-8"); LOG.debug("post uri=[{}], function=[{}], response=[{}]", uri, function, szResponse); break; case HTTP_401_UNAUTHORIZED: error = "post uri=[" + uri + "], function=[" + function + "], 401 function unauthorized on host"; LOG.error(error); throw new RestException(GlobalErrIds.REST_UNAUTHORIZED_ERR, error); case HTTP_403_FORBIDDEN: error = "post uri=[" + uri + "], function=[" + function + "], 403 function forbidden on host"; LOG.error(error); throw new RestException(GlobalErrIds.REST_FORBIDDEN_ERR, error); case HTTP_404_NOT_FOUND: error = "post uri=[" + uri + "], function=[" + function + "], 404 not found from host"; LOG.error(error); throw new RestException(GlobalErrIds.REST_NOT_FOUND_ERR, error); default: error = "post uri=[" + uri + "], function=[" + function + "], error received from host: " + response.getStatusLine().getStatusCode(); LOG.error(error); throw new RestException(GlobalErrIds.REST_UNKNOWN_ERR, error); } } catch (IOException ioe) { String error = "post uri=[" + uri + "], function=[" + function + "] caught IOException=" + ioe; LOG.error(error); throw new RestException(GlobalErrIds.REST_IO_ERR, error, ioe); } catch (WebApplicationException we) { String error = "post uri=[" + uri + "], function=[" + function + "] caught WebApplicationException=" + we; LOG.error(error); throw new RestException(GlobalErrIds.REST_WEB_ERR, error, we); } catch (java.lang.NoSuchMethodError e) { String error = "post uri=[" + uri + "], function=[" + function + "] caught Exception=" + e; LOG.error(error); e.printStackTrace(); throw new RestException(GlobalErrIds.REST_UNKNOWN_ERR, error); } finally { // Release current connection to the connection pool. post.releaseConnection(); } return szResponse; } /** * Perform an HTTP Post REST operation. * * @param szInput * @param function * @return String containing response * @throws RestException */ public String post(String szInput, String function) throws RestException { return post(null, null, szInput, function); } private CredentialsProvider getCredentialProvider(String uid, String password) { BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); credentialsProvider.setCredentials(new AuthScope(httpHost, Integer.valueOf(httpPort)), new UsernamePasswordCredentials(uid == null ? httpUid : uid, password == null ? httpPw : password)); return credentialsProvider; } /** * Set these params into their associated HTTP header vars. * * @param httpRequest */ private static void setMethodHeaders(HttpRequest httpRequest) { if (httpRequest instanceof HttpPost || httpRequest instanceof HttpPut) { httpRequest.addHeader("Content-Type", "application/xml"); httpRequest.addHeader("Accept", "application/xml"); } } /** * Convert from non-Base64 to Base64 encoded. * * @param value * @return String contains encoded data */ private static String base64Encode(String value) { return new String(Base64.encodeBase64(value.getBytes())); } /* private static String base64Encode( String value ) { return Base64Utility.encode( value.getBytes() ); }*/ /** * Process the HTTP method request. * * @param httpGetRequest * @return String containing response * @throws Exception */ private static String handleHttpMethod(HttpRequestBase httpGetRequest, org.apache.http.client.HttpClient client) throws RestException { String szResponse = null; try { HttpResponse response = client.execute(httpGetRequest); LOG.debug("handleHttpMethod Response status : {}", response.getStatusLine().getStatusCode()); Response.Status status = Response.Status.fromStatusCode(response.getStatusLine().getStatusCode()); if (status == Response.Status.OK) { szResponse = IOUtils.toString(response.getEntity().getContent()); LOG.debug(szResponse); } else if (status == Response.Status.FORBIDDEN) { LOG.debug("handleHttpMethod Authorization failure"); } else if (status == Response.Status.UNAUTHORIZED) { LOG.debug("handleHttpMethod Authentication failure"); } else { LOG.debug("handleHttpMethod Unknown error"); } } catch (IOException ioe) { String error = "handleHttpMethod caught IOException=" + ioe; LOG.error(error); throw new RestException(GlobalErrIds.REST_IO_ERR, error, ioe); } finally { // Release current connection to the connection pool. httpGetRequest.releaseConnection(); } return szResponse; } /** * @param inProps * @return Properties */ public static Properties getProperties(Props inProps) { Properties properties = null; List<Props.Entry> props = inProps.getEntry(); if (props.size() > 0) { properties = new Properties(); //int size = props.size(); for (Props.Entry entry : props) { String key = entry.getKey(); String val = entry.getValue(); properties.setProperty(key, val); } } return properties; } /** * * @param properties * @return Prop contains name value pairs. */ public static Props getProps(Properties properties) { Props props = null; if (properties != null) { props = new ObjectFactory().createProps(); for (Enumeration<?> e = properties.propertyNames(); e.hasMoreElements();) { String key = (String) e.nextElement(); String val = properties.getProperty(key); Props.Entry entry = new Props.Entry(); entry.setKey(key); entry.setValue(val); props.getEntry().add(entry); } } return props; } }