public class ExceptionTester {
	
	public static class NoStackTraceException extends Exception {
		
		public NoStackTraceException(String message) {
			super(message);
		}
		
		public synchronized Throwable fillInStackTrace() {
			// on ne fait rien
			return this;
		}
	}
	
	public static class Error {
		private String message;
		
		public Error (String message) {
			this.message = message;
		}
		public String toString() {
			return "Error : " + this.message;
		}
	}

	/**
	 * Exemple de traitement des erreurs en retournant un code d'erreur.
	 * Une erreur est généré si le paramètre est <b>null</b>.
	 * @param param La paramètre de la méthode.
	 * @return -1 en cas d'erreur, 0 sinon.
	 */
    public int methodReturnInt (String param) {
        if (param==null) {
            return -1;
        }
        // traitement
        return 0;
    }
    
    /**
	 * Exemple de traitement des erreurs en retournant un objet.
	 * Une erreur est généré si le paramètre est <b>null</b>.
	 * @param param La paramètre de la méthode.
	 * @return une instance d'Erreur en cas d'erreur, <b>null</b> sinon.
	 */
    public Error methodReturnObject (String param) {
        if (param==null) {
            return new Error("La valeur 'null' n'est pas acceptée");
        }
        // traitement
        return null;
    }
    
    /**
	 * Exemple de traitement des erreurs en retournant un code d'erreur.
	 * Une erreur est généré si le paramètre est <b>null</b>.
	 * @param param La paramètre de la méthode.
     * @throws NoStackTraceException Le paramètre est <b>null</b>.
	 */
    public void methodThrowsNoStack (String param) throws NoStackTraceException {
        if (param==null) {
            throw new NoStackTraceException("La valeur 'null' n'est pas acceptée");
        }
        // traitement
    }
    
    /**
	 * Exemple de traitement des erreurs en retournant un code d'erreur.
	 * Une erreur est généré si le paramètre est <b>null</b>.
	 * @param param La paramètre de la méthode.
     * @throws Exception Le paramètre est <b>null</b>.
	 */
    public void methodThrowsException (String param) throws Exception {
        if (param==null) {
            throw new Exception("La valeur 'null' n'est pas acceptée");
        }
        // traitement
    }
    
    /**
     * Test de performance des différences méthodes de gestion des erreurs.
     * @param param La valeur du paramètre à utiliser.
     * @param iteration Le nombre d'itération a éffectuer.
     */
    public void testPerf (String param, int iteration) {
        long start;
        long duree;
        
        System.out.println(" * " + iteration + " appels de methode avec '"
            + param + "': ");
        
        System.out.print("\t methodReturnInt        : ");
        start = System.currentTimeMillis();
        for (int i=0; i<iteration; i++) {
            switch (methodReturnInt(param)) {
                case -1:
                    // Traitement Erreur
                    break;
                case 0:
                    // Traitement OK
                    break;
            }
        }
        duree = System.currentTimeMillis()-start;
        System.out.println( duree + " ms.");
        
        System.out.print("\t methodReturnObject     : ");
        start = System.currentTimeMillis();
        for (int i=0; i<iteration; i++) {
        	Error error = methodReturnObject(param);
        	if (error!=null) {
        		 // Traitement Erreur
        	} else {
        		// Traitement OK
        	}
        }
        duree = System.currentTimeMillis()-start;
        System.out.println( duree + " ms.");
        

        
        System.out.print("\t methodThrowsNoStack    : ");
        start = System.currentTimeMillis();
        for (int i=0; i<iteration; i++) {
            try {
            	methodThrowsNoStack(param);
                // Traitement OK
            } catch (Exception e){
                // Traitement Erreur
            }
        }
        duree = System.currentTimeMillis()-start;
        System.out.println( duree + " ms.");
        
        System.out.print("\t methodThrowsException  : ");
        start = System.currentTimeMillis();
        for (int i=0; i<iteration; i++) {
            try {
            	methodThrowsException(param);
                // Traitement OK
            } catch (Exception e){
                // Traitement Erreur
            }
        }
        duree = System.currentTimeMillis()-start;
        System.out.println( duree + " ms.");
        System.out.println();
    }
 

    /**
     * Méthode d'entrée dans le programme.
     * @param args ignoré.
     */
    public static void main(String[] args) {
    	
        ExceptionTester obj = new ExceptionTester();
        int iteration = 5000000;
        
        if (args.length>0) {
        	try {
        		iteration = Integer.parseInt(args[0]);
        	} catch (NumberFormatException e) {
        		System.err.println("Le premier paramètre est ignoré (attendu: nombre d'itération).");
        	}
        }

        obj.testPerf("string", iteration);
        obj.testPerf(null, iteration);
    }
}

