View Javadoc

1   //
2   //Copyright (c) 2003, Caltha - Gajda, Krzewski, Mach, Potempski Sp.J.
3   //All rights reserved.
4   //
5   //Redistribution and use in source and binary forms, with or without modification, 
6   //are permitted provided that the following conditions are met:
7   //
8   //* Redistributions of source code must retain the above copyright notice, 
9   //this list of conditions and the following disclaimer.
10  //* Redistributions in binary form must reproduce the above copyright notice, 
11  //this list of conditions and the following disclaimer in the documentation 
12  //and/or other materials provided with the distribution.
13  //* Neither the name of the Caltha - Gajda, Krzewski, Mach, Potempski Sp.J. 
14  //nor the names of its contributors may be used to endorse or promote products 
15  //derived from this software without specific prior written permission.
16  //
17  //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
18  //AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
19  //WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  //IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
21  //INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
22  //BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23  //OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
24  //WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
25  //ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
26  //POSSIBILITY OF SUCH DAMAGE.
27  //
28  
29  package org.objectledge.parameters.db;
30  
31  import java.sql.Connection;
32  import java.sql.PreparedStatement;
33  import java.sql.SQLException;
34  import java.util.ArrayList;
35  import java.util.Arrays;
36  import java.util.Collections;
37  import java.util.Date;
38  import java.util.HashSet;
39  import java.util.Iterator;
40  import java.util.List;
41  import java.util.Set;
42  
43  import org.jcontainer.dna.Logger;
44  import org.objectledge.database.Database;
45  import org.objectledge.database.DatabaseUtils;
46  import org.objectledge.parameters.DefaultParameters;
47  import org.objectledge.parameters.Parameters;
48  import org.objectledge.parameters.ScopedParameters;
49  
50  /**
51   * A persistent implementation of parameters container.
52   *
53   * @author <a href="mailto:pablo@caltha.com">Pawel Potempski</a>
54   * @version $Id: DBParameters.java,v 1.10 2005/12/20 09:09:32 pablo Exp $
55   */
56  public class DBParameters implements Parameters
57  {
58  	/*** the logger */
59  	private Logger logger;
60  
61  	/*** db access component */
62  	private Database database;
63  	
64  	/*** container id */
65  	private long id;
66  
67  	/*** internal container */
68  	private DefaultParameters container;
69      
70      /*** internal container */
71      private DefaultParameters shadow;
72      
73  	/*** modified  */
74  	private HashSet<String> modified;
75      
76      /***
77       * Create the container.
78       * 
79       * @param parameters the initial parameters.
80       * @param id the database identifier.
81       * @param database the db access component
82       * @param logger the logger.
83       */
84      public DBParameters(Parameters parameters, long id, Database database, Logger logger)
85      {
86          modified = new HashSet<String>();
87      	this.logger = logger;
88      	this.database = database;
89      	if(parameters != null)
90      	{
91      	   	container = new DefaultParameters(parameters);
92              shadow = new DefaultParameters(parameters);
93      	}
94      	else
95      	{
96  			container = new DefaultParameters();
97              shadow = new DefaultParameters();
98      	}
99      	this.id = id;
100     }
101 
102 	/***
103 	 * {@inheritDoc}
104 	 */
105     public String get(String name)
106     {
107 		return container.get(name);
108     }
109 
110 	/***
111 	 * {@inheritDoc}
112 	 */
113     public String get(String name, String defaultValue)
114     {
115 		return container.get(name, defaultValue);
116     }
117 
118 	/***
119 	 * {@inheritDoc}
120 	 */
121     public String[] getStrings(String name)
122     {
123 		return container.getStrings(name);    }
124 
125 	/***
126 	 * {@inheritDoc}
127 	 */
128     public boolean getBoolean(String name)
129     {
130 		return container.getBoolean(name);
131     }
132 
133 	/***
134 	 * {@inheritDoc}
135 	 */
136     public boolean getBoolean(String name, boolean defaultValue)
137     {
138 		return container.getBoolean(name, defaultValue);
139     }
140 
141     /***
142      * {@inheritDoc}
143      */
144     public boolean[] getBooleans(String name)
145     {
146 		return container.getBooleans(name);
147     }
148 
149 
150     /***
151      * {@inheritDoc}
152      */
153     public Date getDate(String name)
154     {
155         return container.getDate(name);
156     }
157 
158     /***
159      * {@inheritDoc}
160      */
161     public Date getDate(String name, Date defaultValue)
162     {
163         return container.getDate(name, defaultValue);
164     }
165 
166     /***
167      * {@inheritDoc}
168      */
169     public Date[] getDates(String name)
170     {
171         return container.getDates(name);
172     }
173     
174     /***
175 	 * {@inheritDoc}
176 	 */
177     public float getFloat(String name) throws NumberFormatException
178     {
179 		return container.getFloat(name);
180     }
181 
182 	/***
183 	 * {@inheritDoc}
184 	 */
185     public float getFloat(String name, float defaultValue)
186     {
187 		return container.getFloat(name, defaultValue);
188     }
189 
190     /***
191      * {@inheritDoc}
192      */
193     public float[] getFloats(String name) throws NumberFormatException
194     {
195 		return container.getFloats(name);
196 	}
197 
198 	/***
199 	 * {@inheritDoc}
200 	 */
201     public int getInt(String name) throws NumberFormatException
202     {
203 		return container.getInt(name);
204     	
205     }
206 
207 	/***
208 	 * {@inheritDoc}
209 	 */
210     public int getInt(String name, int defaultValue)
211     {
212 		return container.getInt(name, defaultValue);
213     }
214 
215     /***
216      * {@inheritDoc}
217      */
218     public int[] getInts(String name)
219     {
220 		return container.getInts(name);
221     }
222 
223 	/***
224 	 * {@inheritDoc}
225 	 */
226     public long getLong(String name) throws NumberFormatException
227     {
228 		return container.getLong(name);
229     }
230 
231 	/***
232 	 * {@inheritDoc}
233 	 */
234     public long getLong(String name, long defaultValue)
235     {
236 		return container.getLong(name,defaultValue);
237     }
238     
239 	/***
240 	 * {@inheritDoc}
241 	 */
242 	public long[] getLongs(String name) throws NumberFormatException
243 	{
244 		return container.getLongs(name);
245 	}
246 
247 	/***
248 	 * {@inheritDoc}
249 	 */
250     public String[] getParameterNames()
251     {
252 		return container.getParameterNames();
253     }
254 
255 	/***
256 	 * {@inheritDoc}
257 	 */
258     public boolean isDefined(String name)
259     {
260     	return container.isDefined(name);
261     }
262 
263 	/***
264 	 * {@inheritDoc}
265 	 */
266     public void remove()
267     {
268     	container.remove();
269 		List<String> all = Arrays.asList(container.getParameterNames());
270 		modified.addAll(all);
271 		update();
272     }
273 
274 	/***
275 	 * {@inheritDoc}
276 	 */
277     public void remove(String name)
278     {
279 		container.remove(name);
280 		modified.add(name);
281     	update();    
282     }
283 
284 	/***
285 	 * {@inheritDoc}
286 	 */
287     public void remove(String name, String value)
288     {
289 		container.remove(name,value);
290 		modified.add(name);
291 		update();
292     }
293 
294     /***
295      * {@inheritDoc}
296      */
297     public void remove(String name, Date value)
298     {
299         container.remove(name,value);
300         modified.add(name);
301         update();       
302     }
303 
304     /***
305      * {@inheritDoc}
306      */
307     public void remove(String name, float value)
308     {
309         container.remove(name,value);
310         modified.add(name);
311         update();    	
312     }
313 
314     /***
315      * {@inheritDoc}
316      */
317     public void remove(String name, int value)
318     {
319 		container.remove(name,value);
320 		modified.add(name);
321 		update();    	
322     }
323 
324     /***
325      * {@inheritDoc}
326      */
327     public void remove(String name, long value)
328     {
329 		container.remove(name,value);
330 		modified.add(name);
331 		update();    	
332     }
333     
334 	/***
335 	 * Remove all parameters with a name contained in given set.
336 	 *
337 	 * @param keys the set of keys.
338 	 */
339 	public void remove(Set<String> keys)
340 	{
341 		container.remove(keys);
342 		modified.addAll(keys);
343 		update();    	
344 	}
345     
346 	/***
347 	 * Remove all except those with a keys specified in the set.
348 	 *
349 	 * @param keys the set of names.
350 	 */
351 	public void removeExcept(Set<String> keys)
352 	{
353 		container.removeExcept(keys);
354 		List<String> all = new ArrayList<String>(Arrays.asList(container.getParameterNames()));
355 		all.removeAll(keys);
356 		modified.addAll(all);
357 		update();    	
358 	}
359 
360 	/***
361 	 * {@inheritDoc}
362 	 */
363     public void set(String name, String value)
364     {
365 		container.set(name, value);
366 		modified.add(name);
367 		update();    	
368     }
369 
370     /***
371      * {@inheritDoc}
372      */
373     public void set(String name, String[] values)
374     {
375 		container.set(name, values);
376 		modified.add(name);
377 		update();    	
378     }
379 
380     /***
381      * {@inheritDoc}
382      */
383     public void set(String name, Date value)
384     {
385         container.set(name, value);
386         modified.add(name);
387         update();       
388     }
389 
390     /***
391      * {@inheritDoc}
392      */
393     public void set(String name, Date[] values)
394     {
395         container.set(name, values);
396         modified.add(name);
397         update();       
398     }
399 
400 	/***
401 	 * {@inheritDoc}
402 	 */
403     public void set(String name, boolean value)
404     {
405 		container.set(name, value);
406         modified.add(name);
407         update();    	
408     }
409 
410     /***
411      * {@inheritDoc}
412      */
413     public void set(String name, boolean[] values)
414     {
415 		container.set(name, values);
416 		modified.add(name);
417 		update();    	
418     }
419 
420 	/***
421 	 * {@inheritDoc}
422 	 */
423     public void set(String name, float value)
424     {
425 		container.set(name, value);
426 		modified.add(name);
427 		update();    	
428     }
429 
430     /***
431      * {@inheritDoc}
432      */
433     public void set(String name, float[] values)
434     {
435 		container.set(name, values);
436 		modified.add(name);
437 		update();    	
438     }
439 
440 	/***
441 	 * {@inheritDoc}
442 	 */
443     public void set(String name, int value)
444     {
445 		container.set(name, value);
446 		modified.add(name);
447 		update();    	
448     }
449 
450     /***
451      * {@inheritDoc}
452      */
453     public void set(String name, int[] values)
454     {
455 		container.set(name, values);
456 		modified.add(name);
457 		update();    	
458     }
459 
460 	/***
461 	 * {@inheritDoc}
462 	 */
463     public void set(String name, long value)
464     {
465 		container.set(name, value);
466 		modified.add(name);
467 		update();    	
468     }
469 
470     /***
471      * {@inheritDoc}
472      */
473     public void set(String name, long[] values)
474     {
475 		container.set(name, values);
476 		modified.add(name);
477 		update();    	
478     }
479 
480 	/***
481      * {@inheritDoc}
482      */
483 	public void set(Parameters parameters)
484 	{
485 		String[] names = container.getParameterNames();
486 		for(String name:names)
487 		{
488 			modified.add(name);
489 		}
490 		container.set(parameters);
491 		names = parameters.getParameterNames();
492 		for(String name:names)
493 		{
494 			modified.add(name);
495 		}
496 		update();
497 	}
498 	
499 	/***
500 	 * {@inheritDoc}
501 	 */
502     public void add(String name, String value)
503     {
504 		container.add(name, value);
505 		modified.add(name);
506 		update();    	
507     }
508     
509 	/***
510 	 * {@inheritDoc}
511 	 */
512 	public void add(String name, String[] values)
513 	{
514 		container.add(name, values);
515 		modified.add(name);
516 		update();    	
517 	}
518 
519     /***
520      * {@inheritDoc}
521      */
522     public void add(String name, Date value)
523     {
524         container.add(name, value);
525         modified.add(name);
526         update();       
527     }
528 
529     /***
530      * {@inheritDoc}
531      */
532     public void add(String name, Date[] values)
533     {
534         container.add(name, values);
535         modified.add(name);
536         update();       
537     }
538 
539     /***
540 	 * {@inheritDoc}
541 	 */
542     public void add(String name, boolean value)
543     {
544 		container.add(name, value);
545 		modified.add(name);
546 		update();    	
547     }
548 
549     /***
550      * {@inheritDoc}
551      */
552     public void add(String name, boolean[] values)
553     {
554 		container.add(name, values);
555 		modified.add(name);
556 		update();    	
557     }
558 
559 	/***
560 	 * {@inheritDoc}
561 	 */
562     public void add(String name, float value)
563     {
564 		container.add(name, value);
565 		modified.add(name);
566 		update();    	
567     }
568 
569     /***
570      * {@inheritDoc}
571      */
572     public void add(String name, float[] values)
573     {
574 		container.add(name, values);
575 		modified.add(name);
576 		update();    	
577     }
578 
579 	/***
580 	 * {@inheritDoc}
581 	 */
582     public void add(String name, int value)
583     {
584 		container.add(name, value);
585 		modified.add(name);
586 		update();    	
587     }
588 
589     /***
590      * {@inheritDoc}
591      */
592     public void add(String name, int[] values)
593     {
594 		container.add(name, values);
595 		modified.add(name);
596 		update();    	
597     }
598 
599 	/***
600 	 * {@inheritDoc}
601 	 */
602     public void add(String name, long value)
603     {
604 		container.add(name, value);
605 		modified.add(name);
606 		update();    	
607     }
608 
609     /***
610      * {@inheritDoc}
611      */
612     public void add(String name, long[] values)
613     {
614 		container.add(name, values);
615 		modified.add(name);
616 		update();    	
617     }
618 
619 	/***
620 	 * {@inheritDoc}
621 	 */
622     public void add(Parameters parameters, boolean overwrite)
623     {
624 		container.add(parameters, overwrite);
625 		modified.addAll(Arrays.asList(parameters.getParameterNames()));
626 		update();    	
627     }
628 
629 	/***
630 	 * {@inheritDoc}
631 	 */
632     public String toString()
633     {
634 		return container.toString();
635     }
636 
637 	/***
638 	 * {@inheritDoc}
639 	 */
640     public Parameters getChild(String prefix)
641     {
642         return new ScopedParameters(this, prefix);
643     }
644     
645 	/***
646 	 * Called every time parameter is modified.
647 	 *
648 	 */
649 	private void update()
650 	{
651 		Connection conn = null;
652         boolean isInsert = false;
653         boolean doDelete = false;
654 		try
655 		{
656 			conn = database.getConnection();
657 			Iterator iterator = modified.iterator();
658 			PreparedStatement deleteStmt = conn.prepareStatement(
659 				"DELETE FROM "+DBParametersManager.TABLE_NAME+" where parameters_id = "+id+
660 				" AND name = ?");
661 			PreparedStatement insertStmt = conn.prepareStatement(
662 				"INSERT INTO "+DBParametersManager.TABLE_NAME+" (parameters_id, name, value)" +
663 				" VALUES ("+id+", ?, ?)");
664 			while(iterator.hasNext())
665 			{
666 				String name = (String)iterator.next();
667                 if(!areValuesEqual(name))
668                 {
669     				String[] values = container.getStrings(name);
670     				name = DatabaseUtils.escapeSqlString(name);
671     				deleteStmt.setString(1,name);
672     				deleteStmt.addBatch();
673                     doDelete = true;
674     				for(int j = 0; j < values.length; j++)
675     				{
676                         isInsert = true;
677     					insertStmt.setString(1,name);
678     					insertStmt.setString(2,DatabaseUtils.escapeSqlString(values[j]));
679     					insertStmt.addBatch();
680     				}
681                 }
682 			}
683             if(doDelete)
684             {
685                 deleteStmt.executeBatch();
686             }
687             if(isInsert)
688             {
689     			insertStmt.executeBatch();
690             }
691             shadow = new DefaultParameters(container);
692 		}
693         ///CLOVER:OFF
694 		catch(SQLException e)
695 		{
696 			throw new Error("Exception occurred during parameter update",e);
697 		}
698         ///CLOVER:ON
699 		finally
700 		{
701 			DatabaseUtils.close(conn);
702 		}
703 	}
704     
705     
706     private boolean areValuesEqual(String name)
707     {
708         String[] current = container.getStrings(name);
709         String[] previous = shadow.getStrings(name);
710         if(current.length != previous.length)
711         {
712             return false;
713         }
714         if(current.length == 0)
715         {
716             return true;
717         }
718         if(current.length == 1)
719         {
720             return current[0].equals(previous[0]);
721         }
722         ArrayList<String> currentList = new ArrayList<String>();
723         ArrayList<String> previousList = new ArrayList<String>();
724         for(String temp: current)
725         {
726             currentList.add(temp);
727         }
728         for(String temp: previous)
729         {
730             previousList.add(temp);
731         }
732         Collections.sort(currentList);
733         Collections.sort(previousList);
734         for(int i = 0; i < currentList.size(); i++)
735         {
736             if(!currentList.get(i).equals(previousList.get(i)))
737             {
738                 return false;
739             }
740         }
741         return true;
742     }
743     
744 
745     /***
746      * Get the parameters identifier in database.
747      * 
748      * @return the parameters identifier.
749      */    
750     public long getId()
751     {
752         return id;
753     }
754 }