Java tutorial
/* * Copyright 2012 AMG.lab, a Bull Group Company * * Licensed 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.xlcloud.openstack.client; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import javax.xml.bind.MarshalException; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.xlcloud.openstack.api.IdentityManagementClient; import org.xlcloud.openstack.model.exceptions.OpenStackAuthenticationException; import com.sun.jersey.api.client.ClientHandlerException; /** * This class is a handler set on {@link OpenStackKeystoneClient} when obtained by * {@link OpenStackKeystoneClient#getInstance(String, String, String, String)} method. Every time one of * methods of {@link IdentityManagementClient} is invoked, this invocation is * handled by {@link #invoke(Object, Method, Object[])} method. * * @author Andrzej Stasiak, AMG.net */ public class RefreshAuthenticationHandler implements InvocationHandler { static private final Logger LOG = Logger.getLogger(RefreshAuthenticationHandler.class); public OpenStackKeystoneClient client; private String password; private String username; private String tenantName; /** * @param client * @param username * @param password * @param tenantName */ RefreshAuthenticationHandler(OpenStackKeystoneClient client, String username, String password, String tenantName) { this.client = client; this.username = username; this.password = password; this.tenantName = tenantName; } /** * This method is invoked every time when any * {@link IdentityManagementClient} method is invoked. It checks if * {@link OpenStackKeystoneClient} has any token and if not - tries to authenticate * and then invoke actual method. Otherwise, it invokes actual method and if * OpenStack responds with 401, it tries to authenticate afterwards (to * handle the situation when the token has expired). */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { if (StringUtils.isBlank(client.getToken())) { LOG.info("Token is empty. Authenticating by Keystone."); client.reauthenticate(username, password, tenantName); return this.doInvoke(client, method, args); } else { try { return this.doInvoke(client, method, args); } catch (OpenStackAuthenticationException e) { LOG.info("Got 401 response. Authenticating by Keystone."); client.reauthenticate(username, password, tenantName); return this.doInvoke(client, method, args); } } } catch (ClientHandlerException e) { throw unwrapNoRouteToHostException(e); } } /** * This method checks if the given exception contains MarshalException and if so, * returns exception linked to it. Otherwise, return original exception. * @param e * caught exception * @return input exception or unwrapped NoRouteToHostException */ private Throwable unwrapNoRouteToHostException(ClientHandlerException e) { /* * FIXME ugly NoRouteToHostException recognition. Try to find a better * way... */ if (e.getCause() != null && e.getCause().getCause() instanceof MarshalException) { Throwable linkedException = ((MarshalException) e.getCause().getCause()).getLinkedException(); LOG.warn("Got marshal exception linked with " + linkedException.getClass() + " that will be rethrown."); return linkedException; } else { return e; } } /** * Invokes method (by reflection) and unwraps potential * {@link InvocationTargetException} * * @param target * @param method * @param args * @return * @throws Throwable */ private Object doInvoke(Object target, Method method, Object[] args) throws Throwable { try { return method.invoke(target, args); } catch (InvocationTargetException e) { throw e.getCause(); } } }