View Javadoc
1   /*
2    * Copyright (c) 2002-2021, City of Paris
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met:
8    *
9    *  1. Redistributions of source code must retain the above copyright notice
10   *     and the following disclaimer.
11   *
12   *  2. Redistributions in binary form must reproduce the above copyright notice
13   *     and the following disclaimer in the documentation and/or other materials
14   *     provided with the distribution.
15   *
16   *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17   *     contributors may be used to endorse or promote products derived from
18   *     this software without specific prior written permission.
19   *
20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   * POSSIBILITY OF SUCH DAMAGE.
31   *
32   * License 1.0
33   */
34  package fr.paris.lutece.plugins.captcha.modules.jcaptcha.service.sound;
35  
36  import java.security.SecureRandom;
37  import java.util.Locale;
38  import java.util.Random;
39  
40  import javax.sound.sampled.AudioInputStream;
41  
42  import com.octo.captcha.CaptchaException;
43  import com.octo.captcha.CaptchaQuestionHelper;
44  import com.octo.captcha.component.sound.wordtosound.WordToSound;
45  import com.octo.captcha.component.word.worddecorator.WordDecorator;
46  import com.octo.captcha.component.word.wordgenerator.WordGenerator;
47  import com.octo.captcha.sound.SoundCaptcha;
48  import com.octo.captcha.sound.SoundCaptchaFactory;
49  import com.octo.captcha.sound.gimpy.GimpySound;
50  
51  /**
52   *
53   * @author lutecer
54   *
55   */
56  public class LuteceGimpySoundFactory extends SoundCaptchaFactory
57  {
58      /**
59       * The bundle question key for CaptchaQuestionHelper
60       */
61      public static final String MESSAGE_INVALID_EXCEPTION = "Invalid configuration for a ";
62      public static final String BUNDLE_QUESTION_KEY = GimpySound.class.getName( );
63      private WordGenerator _wordGenerator;
64      private WordToSound _word2Sound;
65      private Random _myRandom = new SecureRandom( );
66  
67      /**
68       * Construct a GimpySoundFactory from a word generator component and a wordtosound component
69       *
70       * @param thewordGenerator
71       *            component
72       * @param theword2Sound
73       *            component
74       */
75      public LuteceGimpySoundFactory( WordGenerator thewordGenerator, WordToSound theword2Sound )
76      {
77          if ( thewordGenerator == null )
78          {
79              throw new CaptchaException( MESSAGE_INVALID_EXCEPTION + "GimpySoundFactory : WordGenerator can't be null" );
80          }
81  
82          if ( theword2Sound == null )
83          {
84              throw new CaptchaException( MESSAGE_INVALID_EXCEPTION + "GimpySoundFactory : Word2Sound can't be null" );
85          }
86  
87          _wordGenerator = thewordGenerator;
88          _word2Sound = theword2Sound;
89      }
90  
91      /**
92       * Construct a GimpySoundFactory from a word generator component and a wordtosound component
93       *
94       * @param wordGenerator
95       *            the wordGenerator component
96       * @param word2Sound
97       *            the word2Sound component
98       * @param wordDecorator
99       *            the word Decodator
100      */
101     public LuteceGimpySoundFactory( WordGenerator wordGenerator, WordToSound word2Sound, WordDecorator wordDecorator )
102     {
103         if ( wordGenerator == null )
104         {
105             throw new CaptchaException( MESSAGE_INVALID_EXCEPTION + "SpellingSoundFactory : WordGenerator can't be null" );
106         }
107 
108         if ( word2Sound == null )
109         {
110             throw new CaptchaException( MESSAGE_INVALID_EXCEPTION + "SpellingSoundFactory : Word2Sound can't be null" );
111         }
112 
113         if ( wordDecorator == null )
114         {
115             throw new CaptchaException( MESSAGE_INVALID_EXCEPTION + "SpellingSoundFactory : wordAbstractor can't be null" );
116         }
117 
118         _wordGenerator = wordGenerator;
119         _word2Sound = word2Sound;
120     }
121 
122     /**
123      *
124      * @return the word to sound
125      */
126     public WordToSound getWordToSound( )
127     {
128         return _word2Sound;
129     }
130 
131     /**
132      *
133      * @return the word generator
134      */
135     public WordGenerator getWordGenerator( )
136     {
137         return _wordGenerator;
138     }
139 
140     /**
141      * @return a Sound Captcha
142      */
143     public SoundCaptcha getSoundCaptcha( )
144     {
145         String word = _wordGenerator.getWord( getRandomLength( ), Locale.getDefault( ) ).toLowerCase( );
146         AudioInputStream sound = _word2Sound.getSound( word );
147         SoundCaptcha soundCaptcha = new GimpySound( getQuestion( Locale.getDefault( ) ), sound, word );
148 
149         return soundCaptcha;
150     }
151 
152     /**
153      * @param locale
154      *            the locale
155      * @return a localized sound captcha
156      */
157     public SoundCaptcha getSoundCaptcha( Locale locale )
158     {
159         String word = _wordGenerator.getWord( getRandomLength( ), locale ).toLowerCase( );
160         AudioInputStream sound = _word2Sound.getSound( word, locale );
161         SoundCaptcha soundCaptcha = new GimpySound( getQuestion( locale ), sound, word );
162 
163         return soundCaptcha;
164     }
165 
166     /**
167      *
168      * @param locale
169      *            the locale
170      * @return the question
171      */
172     protected String getQuestion( Locale locale )
173     {
174         return CaptchaQuestionHelper.getQuestion( locale, BUNDLE_QUESTION_KEY );
175     }
176 
177     /**
178      *
179      * @return the random length of word
180      */
181     protected Integer getRandomLength( )
182     {
183         Integer wordLength;
184         int range = getWordToSound( ).getMaxAcceptedWordLength( ) - getWordToSound( ).getMinAcceptedWordLength( );
185         int randomRange = ( range != 0 ) ? _myRandom.nextInt( range + 1 ) : 0;
186         wordLength = Integer.valueOf( randomRange + getWordToSound( ).getMinAcceptedWordLength( ) );
187 
188         return wordLength;
189     }
190 }