/*************************************************** * * cismet GmbH, Saarbruecken, Germany * * ... and it just works. * ****************************************************/ /* * To change this template, choose Tools | Templates * and open the template in the editor. */ package de.cismet.security; import java.awt.Component; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.io.StringReader; import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Properties; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantReadWriteLock; import de.cismet.commons.security.AccessHandler; import de.cismet.commons.security.AccessHandler.ACCESS_HANDLER_TYPES; import de.cismet.commons.security.AccessHandler.ACCESS_METHODS; import de.cismet.commons.security.Tunnel; import de.cismet.commons.security.TunnelStore; import de.cismet.commons.security.handler.ExtendedAccessHandler; import de.cismet.netutil.Proxy; import de.cismet.security.exceptions.AccessMethodIsNotSupportedException; import de.cismet.security.exceptions.MissingArgumentException; import de.cismet.security.exceptions.NoHandlerForURLException; import de.cismet.security.exceptions.RequestFailedException; import de.cismet.security.handler.DefaultHTTPAccessHandler; import de.cismet.security.handler.FTPAccessHandler; import de.cismet.security.handler.HTTPBasedAccessHandler; import de.cismet.security.handler.WSSAccessHandler; /** * DOCUMENT ME! * * @author spuhl * @version $Revision$, $Date$ */ //ToDO default Handler (HTTP) //ToDo Proxy //ToDO Http Access //ToDo Multithreading //Problematik wenn unter der url mehrere services z.B. wms wfs wss sind //Todo url leichen weil statisch --> wenn versucht wird eine schon vorhandene URL hinzuzufügen --> wir im Moment überschrieben public class WebAccessManager implements AccessHandler, TunnelStore, ExtendedAccessHandler { //~ Static fields/initializers --------------------------------------------- private static WebAccessManager instance = null; private static final ReentrantReadWriteLock reLock = new ReentrantReadWriteLock(); private static final Lock readLock = reLock.readLock(); private static final Lock writeLock = reLock.writeLock(); //~ Instance fields -------------------------------------------------------- private final HashMap<URL, AccessHandler> handlerMapping = new HashMap<URL, AccessHandler>(); private final HashMap<ACCESS_HANDLER_TYPES, AccessHandler> allHandlers = new HashMap<ACCESS_HANDLER_TYPES, AccessHandler>(); private final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(this.getClass()); private ArrayList<ACCESS_HANDLER_TYPES> supportedHandlerTypes = new ArrayList<ACCESS_HANDLER_TYPES>(); private AccessHandler defaultHandler; private Properties serverAliasProps = new Properties(); private Component topLevelComponent = null; private Tunnel tunnel = null; //~ Constructors ----------------------------------------------------------- /** * Creates a new WebAccessManager object. */ private WebAccessManager() { initHandlers(); } //~ Methods ---------------------------------------------------------------- /** * Sets the Proxy-Object of the HTTP- and the WSS-AccessHandler. Does nothing if no HTTP-AccessHandler and no * WSS-AccessHandler exists. * * @param proxy DOCUMENT ME! */ public void setHttpProxy(final Proxy proxy) { // HTTP-Handler holen final AccessHandler httpHandler = allHandlers.get(AccessHandler.ACCESS_HANDLER_TYPES.HTTP); // pruefen ob vom Typ HTTPBasedAccessHandler if ((httpHandler != null) && (httpHandler instanceof HTTPBasedAccessHandler)) { // proxy setzen if (log.isDebugEnabled()) { log.debug("set Proxy in httpHandler"); // NOI18N } ((HTTPBasedAccessHandler)httpHandler).setProxy(proxy); } // WSS-Handler holen final AccessHandler wssHandler = allHandlers.get(AccessHandler.ACCESS_HANDLER_TYPES.WSS); // pruefen ob vom Typ WSSAccessHandler if ((wssHandler != null) && (wssHandler instanceof WSSAccessHandler)) { // proxy setzen if (log.isDebugEnabled()) { log.debug("set Proxy in wssHandler"); // NOI18N } ((WSSAccessHandler)wssHandler).setProxy(proxy); } } /** * DOCUMENT ME! */ public void resetWSSCredentials() { // WSS-Handler holen final AccessHandler wssHandler = allHandlers.get(AccessHandler.ACCESS_HANDLER_TYPES.WSS); // pruefen ob vom Typ WSSAccessHandler if ((wssHandler != null) && (wssHandler instanceof WSSAccessHandler)) { // proxy setzen if (log.isDebugEnabled()) { log.debug("reset WSS credentials"); // NOI18N } ((WSSAccessHandler)wssHandler).resetCredentials(); } } /** * DOCUMENT ME! */ public void resetCredentials() { for (final AccessHandler wmsHandler : allHandlers.values()) { // pruefen ob vom Typ HTTPBasedAccessHandler if ((wmsHandler != null) && (wmsHandler instanceof HTTPBasedAccessHandler)) { // proxy setzen if (log.isDebugEnabled()) { log.debug("reset credentials"); // NOI18N } ((HTTPBasedAccessHandler)wmsHandler).resetCredentials(); } } } /** * Returns the Proxy-Object of the HTTP-AccessHandler or (if it not exists) the Proxy-Object of the * WSS-AccessHandler or null if no proxy exists. * * @return HTTP-AccessHandler or null */ public Proxy getHttpProxy() { // HTTP-Handler holen final AccessHandler httpHandler = allHandlers.get(AccessHandler.ACCESS_HANDLER_TYPES.HTTP); // pruefen ob vom Typ HTTPBasedAccessHandler if ((httpHandler != null) && (httpHandler instanceof HTTPBasedAccessHandler)) { // proxy zurueckgeben return ((HTTPBasedAccessHandler)httpHandler).getProxy(); } else { // WSS-Handler holen final AccessHandler wssHandler = allHandlers.get(AccessHandler.ACCESS_HANDLER_TYPES.WSS); // pruefen ob vom Typ WSSAccessHandler if ((wssHandler != null) && (wssHandler instanceof WSSAccessHandler)) { return ((WSSAccessHandler)wssHandler).getProxy(); } else { return null; } } } /** * ToDO make configurable. */ private void initHandlers() { if (log.isDebugEnabled()) { log.debug("initHandlers"); // NOI18N } final WSSAccessHandler wssHandler = new WSSAccessHandler(); final DefaultHTTPAccessHandler httpHandler = new DefaultHTTPAccessHandler(); final FTPAccessHandler ftpHandler = new FTPAccessHandler(); // SOAPAccessHandler soapAccessHandler = new SOAPAccessHandler(); // SanyAccessHandler sanyAccessHandler = new SanyAccessHandler(); defaultHandler = httpHandler; allHandlers.put(AccessHandler.ACCESS_HANDLER_TYPES.WSS, wssHandler); allHandlers.put(AccessHandler.ACCESS_HANDLER_TYPES.HTTP, httpHandler); allHandlers.put(AccessHandler.ACCESS_HANDLER_TYPES.FTP, ftpHandler); // allHandlers.put(AccessHandler.ACCESS_HANDLER_TYPES.SOAP, soapAccessHandler); // allHandlers.put(AccessHandler.ACCESS_HANDLER_TYPES.SANY, sanyAccessHandler); supportedHandlerTypes.add(ACCESS_HANDLER_TYPES.WSS); supportedHandlerTypes.add(ACCESS_HANDLER_TYPES.HTTP); supportedHandlerTypes.add(ACCESS_HANDLER_TYPES.SOAP); supportedHandlerTypes.add(ACCESS_HANDLER_TYPES.SANY); supportedHandlerTypes.add(ACCESS_HANDLER_TYPES.FTP); } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public AccessHandler getDefaultHandler() { return defaultHandler; } /** * DOCUMENT ME! * * @param defaultHandler DOCUMENT ME! */ public void setDefaultHandler(final AccessHandler defaultHandler) { this.defaultHandler = defaultHandler; } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public static WebAccessManager getInstance() { if (instance != null) { return instance; } else { createInstance(); return instance; } } /** * DOCUMENT ME! */ private static synchronized void createInstance() { if (instance == null) { instance = new WebAccessManager(); } } /** * overwrites at the moment. * * @param url DOCUMENT ME! * @param handlerType DOCUMENT ME! * * @return DOCUMENT ME! */ public synchronized boolean registerAccessHandler(final URL url, final ACCESS_HANDLER_TYPES handlerType) { writeLock.lock(); try { if ((handlerMapping.get(url) == null) && (allHandlers.get(handlerType) != null)) { handlerMapping.put(url, allHandlers.get(handlerType)); return true; } else { // todo einfacher wäre überschreiben ohne zu deregistrieren --> ist synchronisiert if (deregisterAccessHandler(url)) { if (allHandlers.get(handlerType) != null) { handlerMapping.put(url, allHandlers.get(handlerType)); return true; } else { return false; } } else { return false; } } } finally { writeLock.unlock(); } } /** * DOCUMENT ME! * * @param url DOCUMENT ME! * * @return DOCUMENT ME! */ public synchronized boolean deregisterAccessHandler(final URL url) { writeLock.lock(); try { if (handlerMapping.containsKey(url)) { handlerMapping.remove(url); return true; } else { return false; } } finally { writeLock.unlock(); } } /** * DOCUMENT ME! * * @param url DOCUMENT ME! * * @return DOCUMENT ME! */ public boolean isHandlerForURLRegistered(final URL url) { readLock.lock(); try { return handlerMapping.get(url) != null; } finally { readLock.unlock(); } } /** * DOCUMENT ME! * * @param url DOCUMENT ME! * * @return DOCUMENT ME! */ public AccessHandler getHandlerForURL(final URL url) { readLock.lock(); try { final AccessHandler handler = handlerMapping.get(url); if (handler == null) { if (log.isDebugEnabled()) { log.debug("no handler found for url --> try to extract base"); // NOI18N } final String urlString = url.toString(); URL baseURL = null; if (urlString.indexOf('?') != -1) { if (log.isDebugEnabled()) { log.debug("there are parameter appended to the url try to remove"); // NOI18N } try { baseURL = new URL(urlString.substring(0, urlString.indexOf('?'))); return handlerMapping.get(baseURL); } catch (Exception ex) { } } } return handler; } finally { readLock.unlock(); } } /** * DOCUMENT ME! * * @param url DOCUMENT ME! * * @return DOCUMENT ME! */ public ACCESS_HANDLER_TYPES getTypeOfHandler(final URL url) { final AccessHandler accessHandler = handlerMapping.get(url); if (accessHandler != null) { return accessHandler.getHandlerType(); } else { return null; } } /** * DOCUMENT ME! * * @param url DOCUMENT ME! * * @return DOCUMENT ME! * * @throws MissingArgumentException DOCUMENT ME! * @throws AccessMethodIsNotSupportedException DOCUMENT ME! * @throws RequestFailedException DOCUMENT ME! * @throws NoHandlerForURLException DOCUMENT ME! * @throws Exception DOCUMENT ME! */ @Override public InputStream doRequest(final URL url) throws MissingArgumentException, AccessMethodIsNotSupportedException, RequestFailedException, NoHandlerForURLException, Exception { if (log.isDebugEnabled()) { log.debug("URL: " + url + "... trying to retrieve parameters automatically by HTTP_GET"); // NOI18N } URL serviceURL; String requestParameter; try { final String urlString = url.toString(); if (urlString.indexOf('?') != -1) { serviceURL = new URL(urlString.substring(0, urlString.indexOf('?'))); // NOI18N if (log.isDebugEnabled()) { log.debug("service URL: " + serviceURL); // NOI18N } if ((urlString.indexOf('?') + 1) < urlString.length()) { // NOI18N requestParameter = urlString.substring(urlString.indexOf('?') + 1, urlString.length()); // NOI18N if (requestParameter.toLowerCase().contains("service=wss")) { // NOI18N // TODO muss auch wfs fähig sein if (log.isDebugEnabled()) { log.debug("query default WMS"); // NOI18N } requestParameter = "REQUEST=GetCapabilities&service=WMS"; // NOI18N } } else { requestParameter = ""; // NOI18N } if (log.isDebugEnabled()) { log.debug("requestParameter: " + requestParameter); // NOI18N } } else { log.warn("Not able to parse requestparameter (no ?) trying without"); // NOI18N serviceURL = url; requestParameter = ""; // NOI18N } } catch (Exception ex) { // final String errorMessage = "Exception während dem bestimmen der Request Parameter"; final String errorMessage = "Request parameters coud not be parsed: " + ex.getMessage(); // NOI18N log.error(errorMessage); throw new RequestFailedException(errorMessage, ex); } return doRequest(serviceURL, new StringReader(requestParameter), AccessHandler.ACCESS_METHODS.GET_REQUEST); } /** * DOCUMENT ME! * * @param url DOCUMENT ME! * @param requestParameter DOCUMENT ME! * @param accessMethod DOCUMENT ME! * * @return DOCUMENT ME! * * @throws MissingArgumentException DOCUMENT ME! * @throws AccessMethodIsNotSupportedException DOCUMENT ME! * @throws RequestFailedException DOCUMENT ME! * @throws NoHandlerForURLException DOCUMENT ME! * @throws Exception DOCUMENT ME! */ public InputStream doRequest(final URL url, final String requestParameter, final AccessHandler.ACCESS_METHODS accessMethod) throws MissingArgumentException, AccessMethodIsNotSupportedException, RequestFailedException, NoHandlerForURLException, Exception { if (log.isDebugEnabled()) { log.debug("Requestparameter: " + requestParameter); // NOI18N } return doRequest(url, new StringReader(requestParameter), accessMethod); } /** * DOCUMENT ME! * * @param url DOCUMENT ME! * @param requestParameter DOCUMENT ME! * @param accessMethod DOCUMENT ME! * * @return DOCUMENT ME! * * @throws MissingArgumentException DOCUMENT ME! * @throws AccessMethodIsNotSupportedException DOCUMENT ME! * @throws RequestFailedException DOCUMENT ME! * @throws NoHandlerForURLException DOCUMENT ME! * @throws Exception DOCUMENT ME! */ public InputStream doRequest(final URL url, final Reader requestParameter, final AccessHandler.ACCESS_METHODS accessMethod) throws MissingArgumentException, AccessMethodIsNotSupportedException, RequestFailedException, NoHandlerForURLException, Exception { return doRequest(url, requestParameter, accessMethod, null); } /** * DOCUMENT ME! * * @param url DOCUMENT ME! * @param requestParameter DOCUMENT ME! * @param accessMethod DOCUMENT ME! * @param options DOCUMENT ME! * * @return DOCUMENT ME! * * @throws MissingArgumentException DOCUMENT ME! * @throws AccessMethodIsNotSupportedException DOCUMENT ME! * @throws RequestFailedException DOCUMENT ME! * @throws NoHandlerForURLException DOCUMENT ME! * @throws Exception DOCUMENT ME! */ @Override public InputStream doRequest(final URL url, final Reader requestParameter, final AccessHandler.ACCESS_METHODS accessMethod, final HashMap<String, String> options) throws MissingArgumentException, AccessMethodIsNotSupportedException, RequestFailedException, NoHandlerForURLException, Exception { readLock.lock(); if (url == null) { throw new MissingArgumentException("URL is null."); // NOI18N } else if (accessMethod == null) { log.warn("No access method specified. Calling handler's default method."); // NOI18N } if (log.isDebugEnabled()) { log.debug("Request URL: '" + url.toString() + "'."); // NOI18N } final AccessHandler handler; try { handler = handlerMapping.get(url); if (handler != null) { if (log.isDebugEnabled()) { log.debug("Handler for URL '" + url + "' available."); // NOI18N } if (handler.isAccessMethodSupported(accessMethod)) { if (log.isDebugEnabled()) { log.debug("Handler supports access method '" + accessMethod + "'."); // NOI18N } return handler.doRequest(url, requestParameter, accessMethod, options); } else { throw new AccessMethodIsNotSupportedException("The access method '" + accessMethod + "' is not supported by handler '" // NOI18N + handler.getClass() + "'."); // NOI18N } } else { // TODO Default handler if (log.isInfoEnabled()) { log.info("No handler for URL available. Using DefaultHandler."); // NOI18N } if (defaultHandler != null) { return defaultHandler.doRequest(url, requestParameter, accessMethod, options); } else { throw new NoHandlerForURLException("No default handler available."); // NOI18N } } } catch (Exception ex) { log.error("Error while doRequest.", ex); // NOI18N throw ex; } finally { if (log.isDebugEnabled()) { log.debug("Releasing lock."); // NOI18N } readLock.unlock(); } } @Override public InputStream doRequest(final URL url, final InputStream requestParameter, final HashMap<String, String> options) throws MissingArgumentException, AccessMethodIsNotSupportedException, RequestFailedException, NoHandlerForURLException, Exception { readLock.lock(); if (url == null) { throw new MissingArgumentException("URL is null."); // NOI18N } if (log.isDebugEnabled()) { log.debug("Request URL: '" + url.toString() + "'."); // NOI18N } final AccessHandler handler; try { handler = handlerMapping.get(url); if (handler != null) { if (log.isDebugEnabled()) { log.debug("Handler for URL '" + url + "' available."); // NOI18N } if (handler.isAccessMethodSupported(ACCESS_METHODS.POST_REQUEST)) { if (log.isDebugEnabled()) { log.debug("Handler supports access method + '" + ACCESS_METHODS.POST_REQUEST + "'."); // NOI18N } return handler.doRequest(url, requestParameter, options); } else { throw new AccessMethodIsNotSupportedException("The access method '" + ACCESS_METHODS.POST_REQUEST + "' is not supported by handler '" // NOI18N + handler.getClass() + "'."); // NOI18N } } else { // TODO Default handler if (log.isInfoEnabled()) { log.info("No handler for URL available. Using default handler."); // NOI18N } if (defaultHandler != null) { return defaultHandler.doRequest(url, requestParameter, options); } else { throw new NoHandlerForURLException("No default handler available."); // NOI18N } } } catch (Exception ex) { log.error("Error while doRequest.", ex); // NOI18N throw ex; } finally { if (log.isDebugEnabled()) { log.debug("Releasing lock."); // NOI18N } readLock.unlock(); } } /** * Checks with a HEAD request, if an URL is accessible or not. * * <p>Note: The method might return false, even if the URL exists, because of network problems or permission issues * etc...</p> * * @param url DOCUMENT ME! * * @return true: the URL is accessible. Otherwise false */ @Override public boolean checkIfURLaccessible(final URL url) { boolean urlAccessible = false; // if the URL is accessible an InputStream is returned. Otherwise an Exception is thrown. As the URL might not // be accessible, the exceptions are only logged in the debug mode. InputStream inputStream = null; try { inputStream = this.doRequest(url, "", AccessHandler.ACCESS_METHODS.HEAD_REQUEST); urlAccessible = (inputStream != null) ? true : false; } catch (final MissingArgumentException ex) { if (log.isDebugEnabled()) { log.debug("Could not read document from URL '" + url.toExternalForm() + "'.", ex); } } catch (final AccessMethodIsNotSupportedException ex) { if (log.isDebugEnabled()) { log.debug("Can't access document URL '" + url.toExternalForm() + "' with default access method.", ex); } } catch (final RequestFailedException ex) { if (log.isDebugEnabled()) { log.debug("Requesting document from URL '" + url.toExternalForm() + "' failed.", ex); } } catch (final NoHandlerForURLException ex) { if (log.isDebugEnabled()) { log.debug("Can't handle URL '" + url.toExternalForm() + "'.", ex); } } catch (final Exception ex) { if (log.isDebugEnabled()) { log.debug("An exception occurred while opening URL '" + url.toExternalForm() + "'.", ex); } } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException ex) { log.warn("Could not close stream.", ex); } } } return urlAccessible; } /** * TODO keine Funktionalität --> nur dummies zur kompatibilität. * * @param key DOCUMENT ME! * @param value DOCUMENT ME! */ public void addServerAliasProperty(final String key, final String value) { serverAliasProps.put(key, value); } /** * DOCUMENT ME! * * @param key DOCUMENT ME! * * @return DOCUMENT ME! */ public String getServerAliasProperty(final String key) { return serverAliasProps.getProperty(key); } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public Component getTopLevelComponent() { return topLevelComponent; } /** * DOCUMENT ME! * * @param topLevelComponent DOCUMENT ME! */ public void setTopLevelComponent(final Component topLevelComponent) { this.topLevelComponent = topLevelComponent; } /** * todo. * * @return DOCUMENT ME! * * @throws UnsupportedOperationException DOCUMENT ME! */ @Override public ACCESS_HANDLER_TYPES getHandlerType() { throw new UnsupportedOperationException("Not supported yet."); // NOI18N } /** * todo. * * @param method DOCUMENT ME! * * @return DOCUMENT ME! * * @throws UnsupportedOperationException DOCUMENT ME! */ @Override public boolean isAccessMethodSupported(final ACCESS_METHODS method) { throw new UnsupportedOperationException("Not supported yet."); // NOI18N } @Override public Tunnel getTunnel() { return tunnel; } @Override public void setTunnel(final Tunnel tunnel) { this.tunnel = tunnel; final Collection<AccessHandler> c = allHandlers.values(); for (final AccessHandler a : c) { if (a instanceof TunnelStore) { ((TunnelStore)a).setTunnel(tunnel); } } if (!c.contains(defaultHandler)) { if (defaultHandler instanceof TunnelStore) { ((TunnelStore)defaultHandler).setTunnel(tunnel); } } } }