Coverage report

  %line %branch
nl.toolforge.karma.core.vc.Authenticators
47% 
78% 

 1  
 /*
 2  
 Karma core - Core of the Karma application
 3  
 Copyright (C) 2004  Toolforge <www.toolforge.nl>
 4  
 
 5  
 This library is free software; you can redistribute it and/or
 6  
 modify it under the terms of the GNU Lesser General Public
 7  
 License as published by the Free Software Foundation; either
 8  
 version 2.1 of the License, or (at your option) any later version.
 9  
 
 10  
 This library is distributed in the hope that it will be useful,
 11  
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13  
 Lesser General Public License for more details.
 14  
 
 15  
 You should have received a copy of the GNU Lesser General Public
 16  
 License along with this library; if not, write to the Free Software
 17  
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 18  
 */
 19  
 package nl.toolforge.karma.core.vc;
 20  
 
 21  
 import nl.toolforge.karma.core.KarmaRuntimeException;
 22  
 import nl.toolforge.karma.core.boot.WorkingContext;
 23  
 import nl.toolforge.karma.core.location.PasswordScrambler;
 24  
 import org.apache.commons.digester.Digester;
 25  
 import org.apache.commons.logging.Log;
 26  
 import org.apache.commons.logging.LogFactory;
 27  
 import org.xml.sax.SAXException;
 28  
 
 29  
 import java.io.File;
 30  
 import java.io.FileWriter;
 31  
 import java.io.IOException;
 32  
 import java.text.MessageFormat;
 33  
 import java.util.ArrayList;
 34  
 import java.util.HashMap;
 35  
 import java.util.Hashtable;
 36  
 import java.util.Iterator;
 37  
 import java.util.List;
 38  
 import java.util.Map;
 39  
 
 40  
 /**
 41  
  * <p>When a {@link nl.toolforge.karma.core.location.Location} - more specifically, {@link VersionControlSystem} -
 42  
  * requires authentication, Karma provides for a mechanism whereby an d<code>authenticators.xml</code>, located in the
 43  
  * Karma configuration directory stores a username. Depending on the specific implementation of
 44  
  * <code>VersionControlSystem</code>, password info is then retrieved.
 45  
  *
 46  
  * <p>The <code>Authenticator</code> class reads the <code>authenticators.xml</code> from the Karma configuration
 47  
  * directory and can then map <code>VersionControlSystem</code> instances by checking if an <code>authenticator</code>
 48  
  * element is present for the location. This mapping is done by checking if the <code>id</code> attributes for the
 49  
  * <code>location</code> and the <code>authenticator</code> are the same.
 50  
  *
 51  
  * @author D.A. Smedes
 52  
  * @version $Id: Authenticators.java,v 1.6 2004/11/03 20:53:19 asmedes Exp $
 53  
  */
 54  
 public final class Authenticators {
 55  
 
 56  280
   private static Log logger = LogFactory.getLog(Authenticators.class);
 57  
 
 58  
   /**
 59  
    * Singleton, helper.
 60  
    */
 61  0
   private Authenticators() {}
 62  
 
 63  
   public static synchronized void changePassword(AuthenticatorKey key, String newPassword) throws AuthenticationException {
 64  
 
 65  0
     if (key == null) {
 66  0
       throw new IllegalArgumentException("Authenticator key cannot be null.");
 67  
     }
 68  
 
 69  0
     Map authenticators = getAuthenticators();
 70  
 
 71  0
     Authenticator authenticator = ((Authenticator) authenticators.get(key));
 72  
 
 73  0
     if (authenticator == null) {
 74  0
       throw new AuthenticationException(AuthenticationException.AUTHENTICATOR_NOT_FOUND, class="keyword">new Object[]{key});
 75  
     }
 76  
 
 77  0
     authenticator.setPassword(PasswordScrambler.scramble(newPassword));
 78  
 
 79  
     try {
 80  0
       flush(authenticators);
 81  0
     } catch (IOException e) {
 82  0
       throw new AuthenticationException(e, AuthenticationException.AUTHENTICATOR_WRITE_ERROR);
 83  0
     }
 84  0
   }
 85  44
 
 86  4
   public static Authenticator getAuthenticator(Authenticator authenticator) throws AuthenticationException {
 87  56
     return getAuthenticator(authenticator.getAuthenticatorKey());
 88  
   }
 89  
 
 90  
   /**
 91  1198
    * Retrieves an <code>Authenticator</code> entry from the <code>authenticators.xml</code> file.
 92  38
    *
 93  
    * @param key                      The key by which the <code>Authenticator</code> will be located.
 94  
    * @return                         The <code>Authenticator</code> with key <code>key</code>.
 95  1198
    * @throws AuthenticationException When no <code>Authenticator</code> can be found with key <code>key</code>.
 96  38
    */
 97  1198
   public static Authenticator getAuthenticator(AuthenticatorKey key) throws AuthenticationException {
 98  728
 
 99  532
     if (key == null) {
 100  0
       throw new IllegalArgumentException("Authenticator key cannot be null.");
 101  508
     }
 102  38
 
 103  532
     Authenticator authenticator = ((Authenticator) getAuthenticators().get(key));
 104  
 
 105  532
     if (authenticator == null) {
 106  1198
       throw new AuthenticationException(AuthenticationException.AUTHENTICATOR_NOT_FOUND, class="keyword">new Object[]{key});
 107  38
     }
 108  1198
 
 109  570
     return authenticator;
 110  1198
   }
 111  388
 
 112  70
   private static Map authenticatorCache = null;
 113  70
   private static long lastModified = 0l;
 114  
 
 115  
   private synchronized static Map getAuthenticators() throws AuthenticationException {
 116  1198
 
 117  570
     File authenticatorsFile = new File(WorkingContext.getConfigurationBaseDir(), "authenticators.xml");
 118  1198
 
 119  570
     if (!authenticatorsFile.exists()) {
 120  1198
       createNew();
 121  38
     }
 122  
 
 123  532
     if (authenticatorCache == null) {
 124  70
       authenticatorCache = new Hashtable();
 125  1268
       logger.debug("Creating authenticator cache from `authenticators.xml`.");
 126  38
     } else {
 127  1198
 
 128  4102
       // Check if the file has been changed outside the running Karma.
 129  4368
       //
 130  4830
       if (authenticatorsFile.lastModclass="keyword">ified() == lastModclass="keyword">ified) {
 131  673
         logger.debug("Using authenticator cache.");
 132  369
         return authenticatorCache;
 133  
       } else {
 134  93
         authenticatorCache = new Hashtable();
 135  93
         logger.debug("Recreating authenticator cache from `authenticators.xml`.");
 136  4064
       }
 137  304
     }
 138  1198
 
 139  38
     // Create a list of authenticators, anything you can find.
 140  
     //
 141  163
     Digester digester = getDigester();
 142  
 
 143  163
     List subList = null;
 144  
     try {
 145  163
       subList = (List) digester.parse(authenticatorsFile.getPath());
 146  0
     } catch (IOException e) {
 147  0
       throw new AuthenticationException(e, AuthenticationException.MISSING_AUTHENTICATOR_CONFIGURATION);
 148  0
     } catch (SAXException e) {
 149  0
       throw new AuthenticationException(e, AuthenticationException.AUTHENTICATOR_LOAD_ERROR);
 150  163
     }
 151  
 
 152  163
     for (Iterator j = subList.iterator(); j.hasNext();) {
 153  1304
       Authenticator authDescriptor = (Authenticator) j.next();
 154  1304
       AuthenticatorKey key = new AuthenticatorKey(authDescriptor.getWorkingContext(), authDescriptor.getId());
 155  1304
       if (authenticatorCache.containsKey(key)) {
 156  0
         throw new AuthenticationException(
 157  
             AuthenticationException.DUPLICATE_AUTHENTICATOR_KEY,
 158  
             new Object[] {key, WorkingContext.getConfigurationBaseDir().getPath()}
 159  
         );
 160  
       }
 161  1304
       authenticatorCache.put(key, authDescriptor);
 162  
     }
 163  
 
 164  
     // Maintain the lastModified time.
 165  
     //
 166  163
     lastModified = authenticatorsFile.lastModified();
 167  
 
 168  163
     return authenticatorCache;
 169  
   }
 170  
 
 171  
   /**
 172  
    * Adds an authenticator to <code>authenticators.xml</code> if the authenticator does not yet exist.
 173  
    *
 174  
    * @param authenticator
 175  
    */
 176  
   public static synchronized void addAuthenticator(Authenticator authenticator) throws AuthenticationException {
 177  
 
 178  0
     if (authenticator == null) {
 179  0
       throw new IllegalArgumentException("Authenticator cannot be null.");
 180  
     }
 181  
 
 182  
     // Add the authenticator.
 183  
     //
 184  0
     getAuthenticators().put(authenticator.getAuthenticatorKey(), authenticator);
 185  
 
 186  
     try {
 187  0
       flush(getAuthenticators());
 188  0
     } catch (IOException e) {
 189  0
       throw new KarmaRuntimeException(e);
 190  0
     }
 191  0
   }
 192  
 
 193  
   /**
 194  
    * Deletes an authenticator entry from <code>authenticators.xml</code>.
 195  
    *
 196  
    * @param authenticator
 197  
    */
 198  
   public static synchronized void deleteAuthenticator(Authenticator authenticator) throws AuthenticationException {
 199  
 
 200  
     // Add the authenticator.
 201  
     //
 202  0
     getAuthenticators().remove(new AuthenticatorKey(authenticator.getWorkingContext(), authenticator.getWorkingContext()));
 203  
 
 204  
     try {
 205  350
       flush(getAuthenticators());
 206  0
     } catch (IOException e) {
 207  0
       throw new KarmaRuntimeException(e);
 208  350
     }
 209  350
   }
 210  
 
 211  
   private static void createNew() throws AuthenticationException {
 212  
     try {
 213  350
       flush(new HashMap());
 214  0
     } catch (IOException e) {
 215  350
       throw new AuthenticationException(e, AuthenticationException.MISSING_AUTHENTICATOR_CONFIGURATION);
 216  350
     }
 217  0
   }
 218  350
 
 219  
   private static synchronized void flush(Map authenticators) throws IOException {
 220  
 
 221  0
     StringBuffer buffer = new StringBuffer();
 222  
 
 223  0
     buffer.append("<?xml version=\ŕ.0\"?>\n\n");
 224  0
     buffer.append("<authenticators>\n");
 225  
 
 226  0
     for (Iterator i = authenticators.values().iterator(); i.hasNext();) {
 227  0
       MessageFormat formatter = null;
 228  
 
 229  0
       Authenticator a = (Authenticator) i.next();
 230  0
       if (a.getPassword() != null) {
 231  0
         formatter = new MessageFormat("  <authenticator working-context=\"{0}\" id=\"{1}\" username=\"{2}\" password=\"{3}\"/>\n");
 232  
 
 233  
         // todo I guess there is some default toolie available for this (XML escaper).
 234  
 
 235  0
         String password = a.getPassword();
 236  0
         password = password.replaceAll("&", "&amp;");
 237  0
         password = password.replaceAll("<", "&lt;");
 238  0
         password = password.replaceAll(">", "&gt;");
 239  0
         password = password.replaceAll("\"", "&quot;");
 240  0
         password = password.replaceAll("'", "&apos;");
 241  350
 
 242  0
         buffer.append(formatter.format(new String[]{a.getWorkingContext(), a.getId(), a.getUsername(), password}));
 243  350
       } else {
 244  0
         formatter = new MessageFormat("  <authenticator working-context=\"{0}\" id=\"{1}\" username=\"{2}\"/>\n");
 245  0
         buffer.append(formatter.format(new String[]{a.getWorkingContext(), a.getId(), a.getUsername()}));
 246  350
       }
 247  
     }
 248  
 
 249  350
     buffer.append("</authenticators>\n");
 250  350
 
 251  0
     FileWriter writer = null;
 252  
     // Write the manifest to the manifest store.
 253  350
     //
 254  350
     writer = new FileWriter(class="keyword">new File(WorkingContext.getConfigurationBaseDir(), "authenticators.xml"));
 255  350
     try {
 256  
 
 257  0
       writer.write(buffer.toString());
 258  0
       writer.flush();
 259  1198
 
 260  38
     } finally {
 261  1468
       writer.close();
 262  1246
     }
 263  1236
   }
 264  1236
 
 265  1236
   private static Digester getDigester() {
 266  1236
 
 267  201
     Digester digester = new Digester();
 268  
 
 269  163
     digester.addObjectCreate("authenticators", ArrayList.class);
 270  163
     digester.addObjectCreate("authenticators/authenticator", Authenticator.class);
 271  163
     digester.addSetProperties("authenticators/authenticator");
 272  163
     digester.addSetProperties("authenticators/authenticator", new String[]{"working-context"}, new String[]{"workingContext"});
 273  163
     digester.addSetNext("authenticators/authenticator", "add");
 274  163
     return digester;
 275  
   }
 276  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.