KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > mysql > jdbc > jdbc2 > optional > StatementWrapper


1 /*
2    Copyright (C) 2004 MySQL AB
3    
4       This program is free software; you can redistribute it and/or modify
5       it under the terms of the GNU General Public License as published by
6       the Free Software Foundation; either version 2 of the License, or
7       (at your option) any later version.
8    
9       This program is distributed in the hope that it will be useful,
10       but WITHOUT ANY WARRANTY; without even the implied warranty of
11       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12       GNU General Public License for more details.
13    
14       You should have received a copy of the GNU General Public License
15       along with this program; if not, write to the Free Software
16       Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17       
18  */

19 package com.mysql.jdbc.jdbc2.optional;
20
21 import com.mysql.jdbc.SQLError;
22
23 import java.sql.Connection JavaDoc;
24 import java.sql.ResultSet JavaDoc;
25 import java.sql.SQLException JavaDoc;
26 import java.sql.SQLWarning JavaDoc;
27 import java.sql.Statement JavaDoc;
28
29
30 /**
31  * Wraps statements so that errors can be reported correctly to
32  * ConnectionEventListeners.
33  *
34  * @author Mark Matthews
35  *
36  * @version $Id: StatementWrapper.java,v 1.1.2.1 2004/02/13 17:55:30 mmatthew Exp $
37  */

38 class StatementWrapper extends WrapperBase implements Statement JavaDoc {
39     protected Statement JavaDoc wrappedStmt;
40
41     protected StatementWrapper(MysqlPooledConnection conn, Statement JavaDoc toWrap) {
42         this.pooledConnection = conn;
43         this.wrappedStmt = toWrap;
44     }
45
46     /* (non-Javadoc)
47      * @see java.sql.Statement#getConnection()
48      */

49     public Connection JavaDoc getConnection() throws SQLException JavaDoc {
50         try {
51             if (this.wrappedStmt != null) {
52                 return this.wrappedStmt.getConnection();
53             } else {
54                 throw new SQLException JavaDoc("Statement already closed",
55                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
56             }
57         } catch (SQLException JavaDoc sqlEx) {
58             checkAndFireConnectionError(sqlEx);
59         }
60
61         return null; // we actually never get here, but the compiler can't figure
62

63         // that out
64
}
65
66     /* (non-Javadoc)
67      * @see java.sql.Statement#setCursorName(java.lang.String)
68      */

69     public void setCursorName(String JavaDoc name) throws SQLException JavaDoc {
70         try {
71             if (this.wrappedStmt != null) {
72                 this.wrappedStmt.setCursorName(name);
73             } else {
74                 throw new SQLException JavaDoc("Statement already closed",
75                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
76             }
77         } catch (SQLException JavaDoc sqlEx) {
78             checkAndFireConnectionError(sqlEx);
79         }
80     }
81
82     /* (non-Javadoc)
83      * @see java.sql.Statement#setEscapeProcessing(boolean)
84      */

85     public void setEscapeProcessing(boolean enable) throws SQLException JavaDoc {
86         try {
87             if (this.wrappedStmt != null) {
88                 this.wrappedStmt.setEscapeProcessing(enable);
89             } else {
90                 throw new SQLException JavaDoc("Statement already closed",
91                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
92             }
93         } catch (SQLException JavaDoc sqlEx) {
94             checkAndFireConnectionError(sqlEx);
95         }
96     }
97
98     /* (non-Javadoc)
99      * @see java.sql.Statement#setFetchDirection(int)
100      */

101     public void setFetchDirection(int direction) throws SQLException JavaDoc {
102         try {
103             if (this.wrappedStmt != null) {
104                 this.wrappedStmt.setFetchDirection(direction);
105             } else {
106                 throw new SQLException JavaDoc("Statement already closed",
107                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
108             }
109         } catch (SQLException JavaDoc sqlEx) {
110             checkAndFireConnectionError(sqlEx);
111         }
112     }
113
114     /* (non-Javadoc)
115      * @see java.sql.Statement#getFetchDirection()
116      */

117     public int getFetchDirection() throws SQLException JavaDoc {
118         try {
119             if (this.wrappedStmt != null) {
120                 return this.wrappedStmt.getFetchDirection();
121             } else {
122                 throw new SQLException JavaDoc("Statement already closed",
123                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
124             }
125         } catch (SQLException JavaDoc sqlEx) {
126             checkAndFireConnectionError(sqlEx);
127         }
128
129         return ResultSet.FETCH_FORWARD; // we actually never get here, but the compiler can't figure
130

131         // that out
132
}
133
134     /* (non-Javadoc)
135      * @see java.sql.Statement#setFetchSize(int)
136      */

137     public void setFetchSize(int rows) throws SQLException JavaDoc {
138         try {
139             if (this.wrappedStmt != null) {
140                 this.wrappedStmt.setFetchSize(rows);
141             } else {
142                 throw new SQLException JavaDoc("Statement already closed",
143                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
144             }
145         } catch (SQLException JavaDoc sqlEx) {
146             checkAndFireConnectionError(sqlEx);
147         }
148     }
149
150     /* (non-Javadoc)
151      * @see java.sql.Statement#getFetchSize()
152      */

153     public int getFetchSize() throws SQLException JavaDoc {
154         try {
155             if (this.wrappedStmt != null) {
156                 return this.wrappedStmt.getFetchSize();
157             } else {
158                 throw new SQLException JavaDoc("Statement already closed",
159                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
160             }
161         } catch (SQLException JavaDoc sqlEx) {
162             checkAndFireConnectionError(sqlEx);
163         }
164
165         return 0; // we actually never get here, but the compiler can't figure
166

167         // that out
168
}
169
170     /* (non-Javadoc)
171      * @see java.sql.Statement#getGeneratedKeys()
172      */

173     public ResultSet JavaDoc getGeneratedKeys() throws SQLException JavaDoc {
174         try {
175             if (this.wrappedStmt != null) {
176                 return this.wrappedStmt.getGeneratedKeys();
177             } else {
178                 throw new SQLException JavaDoc("Statement already closed",
179                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
180             }
181         } catch (SQLException JavaDoc sqlEx) {
182             checkAndFireConnectionError(sqlEx);
183         }
184
185         return null; // we actually never get here, but the compiler can't figure
186

187         // that out
188
}
189
190     /* (non-Javadoc)
191      * @see java.sql.Statement#setMaxFieldSize(int)
192      */

193     public void setMaxFieldSize(int max) throws SQLException JavaDoc {
194         try {
195             if (this.wrappedStmt != null) {
196                 this.wrappedStmt.setMaxFieldSize(max);
197             } else {
198                 throw new SQLException JavaDoc("Statement already closed",
199                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
200             }
201         } catch (SQLException JavaDoc sqlEx) {
202             checkAndFireConnectionError(sqlEx);
203         }
204     }
205
206     /* (non-Javadoc)
207      * @see java.sql.Statement#getMaxFieldSize()
208      */

209     public int getMaxFieldSize() throws SQLException JavaDoc {
210         try {
211             if (this.wrappedStmt != null) {
212                 return this.wrappedStmt.getMaxFieldSize();
213             } else {
214                 throw new SQLException JavaDoc("Statement already closed",
215                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
216             }
217         } catch (SQLException JavaDoc sqlEx) {
218             checkAndFireConnectionError(sqlEx);
219         }
220
221         return 0; // we actually never get here, but the compiler can't figure
222

223         // that out
224
}
225
226     /* (non-Javadoc)
227      * @see java.sql.Statement#setMaxRows(int)
228      */

229     public void setMaxRows(int max) throws SQLException JavaDoc {
230         try {
231             if (this.wrappedStmt != null) {
232                 this.wrappedStmt.setMaxRows(max);
233             } else {
234                 throw new SQLException JavaDoc("Statement already closed",
235                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
236             }
237         } catch (SQLException JavaDoc sqlEx) {
238             checkAndFireConnectionError(sqlEx);
239         }
240     }
241
242     /* (non-Javadoc)
243      * @see java.sql.Statement#getMaxRows()
244      */

245     public int getMaxRows() throws SQLException JavaDoc {
246         try {
247             if (this.wrappedStmt != null) {
248                 return this.wrappedStmt.getMaxRows();
249             } else {
250                 throw new SQLException JavaDoc("Statement already closed",
251                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
252             }
253         } catch (SQLException JavaDoc sqlEx) {
254             checkAndFireConnectionError(sqlEx);
255         }
256
257         return 0; // we actually never get here, but the compiler can't figure
258

259         // that out
260
}
261
262     /* (non-Javadoc)
263      * @see java.sql.Statement#getMoreResults()
264      */

265     public boolean getMoreResults() throws SQLException JavaDoc {
266         try {
267             if (this.wrappedStmt != null) {
268                 return this.wrappedStmt.getMoreResults();
269             } else {
270                 throw new SQLException JavaDoc("Statement already closed",
271                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
272             }
273         } catch (SQLException JavaDoc sqlEx) {
274             checkAndFireConnectionError(sqlEx);
275         }
276
277         return false;
278     }
279
280     /* (non-Javadoc)
281      * @see java.sql.Statement#getMoreResults(int)
282      */

283     public boolean getMoreResults(int current) throws SQLException JavaDoc {
284         try {
285             if (this.wrappedStmt != null) {
286                 return this.wrappedStmt.getMoreResults(current);
287             } else {
288                 throw new SQLException JavaDoc("Statement already closed",
289                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
290             }
291         } catch (SQLException JavaDoc sqlEx) {
292             checkAndFireConnectionError(sqlEx);
293         }
294
295         return false;
296     }
297
298     /* (non-Javadoc)
299      * @see java.sql.Statement#setQueryTimeout(int)
300      */

301     public void setQueryTimeout(int seconds) throws SQLException JavaDoc {
302         try {
303             if (this.wrappedStmt != null) {
304                 this.wrappedStmt.setQueryTimeout(seconds);
305             } else {
306                 throw new SQLException JavaDoc("Statement already closed",
307                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
308             }
309         } catch (SQLException JavaDoc sqlEx) {
310             checkAndFireConnectionError(sqlEx);
311         }
312     }
313
314     /* (non-Javadoc)
315      * @see java.sql.Statement#getQueryTimeout()
316      */

317     public int getQueryTimeout() throws SQLException JavaDoc {
318         try {
319             if (this.wrappedStmt != null) {
320                 return this.wrappedStmt.getQueryTimeout();
321             } else {
322                 throw new SQLException JavaDoc("Statement already closed",
323                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
324             }
325         } catch (SQLException JavaDoc sqlEx) {
326             checkAndFireConnectionError(sqlEx);
327         }
328
329         return 0;
330     }
331
332     /* (non-Javadoc)
333      * @see java.sql.Statement#getResultSet()
334      */

335     public ResultSet JavaDoc getResultSet() throws SQLException JavaDoc {
336         try {
337             if (this.wrappedStmt != null) {
338                 return this.wrappedStmt.getResultSet();
339             } else {
340                 throw new SQLException JavaDoc("Statement already closed",
341                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
342             }
343         } catch (SQLException JavaDoc sqlEx) {
344             checkAndFireConnectionError(sqlEx);
345         }
346
347         return null;
348     }
349
350     /* (non-Javadoc)
351      * @see java.sql.Statement#getResultSetConcurrency()
352      */

353     public int getResultSetConcurrency() throws SQLException JavaDoc {
354         try {
355             if (this.wrappedStmt != null) {
356                 return this.wrappedStmt.getResultSetConcurrency();
357             } else {
358                 throw new SQLException JavaDoc("Statement already closed",
359                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
360             }
361         } catch (SQLException JavaDoc sqlEx) {
362             checkAndFireConnectionError(sqlEx);
363         }
364
365         return 0;
366     }
367
368     /* (non-Javadoc)
369      * @see java.sql.Statement#getResultSetHoldability()
370      */

371     public int getResultSetHoldability() throws SQLException JavaDoc {
372         try {
373             if (this.wrappedStmt != null) {
374                 return this.wrappedStmt.getResultSetHoldability();
375             } else {
376                 throw new SQLException JavaDoc("Statement already closed",
377                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
378             }
379         } catch (SQLException JavaDoc sqlEx) {
380             checkAndFireConnectionError(sqlEx);
381         }
382
383         return Statement.CLOSE_CURRENT_RESULT;
384     }
385
386     /* (non-Javadoc)
387      * @see java.sql.Statement#getResultSetType()
388      */

389     public int getResultSetType() throws SQLException JavaDoc {
390         try {
391             if (this.wrappedStmt != null) {
392                 return this.wrappedStmt.getResultSetType();
393             } else {
394                 throw new SQLException JavaDoc("Statement already closed",
395                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
396             }
397         } catch (SQLException JavaDoc sqlEx) {
398             checkAndFireConnectionError(sqlEx);
399         }
400
401         return ResultSet.TYPE_FORWARD_ONLY;
402     }
403
404     /* (non-Javadoc)
405      * @see java.sql.Statement#getUpdateCount()
406      */

407     public int getUpdateCount() throws SQLException JavaDoc {
408         try {
409             if (this.wrappedStmt != null) {
410                 return this.wrappedStmt.getUpdateCount();
411             } else {
412                 throw new SQLException JavaDoc("Statement already closed",
413                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
414             }
415         } catch (SQLException JavaDoc sqlEx) {
416             checkAndFireConnectionError(sqlEx);
417         }
418
419         return -1;
420     }
421
422     /* (non-Javadoc)
423      * @see java.sql.Statement#getWarnings()
424      */

425     public SQLWarning JavaDoc getWarnings() throws SQLException JavaDoc {
426         try {
427             if (this.wrappedStmt != null) {
428                 return this.wrappedStmt.getWarnings();
429             } else {
430                 throw new SQLException JavaDoc("Statement already closed",
431                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
432             }
433         } catch (SQLException JavaDoc sqlEx) {
434             checkAndFireConnectionError(sqlEx);
435         }
436
437         return null;
438     }
439
440     /* (non-Javadoc)
441      * @see java.sql.Statement#addBatch(java.lang.String)
442      */

443     public void addBatch(String JavaDoc sql) throws SQLException JavaDoc {
444         try {
445             if (this.wrappedStmt != null) {
446                 this.wrappedStmt.addBatch(sql);
447             }
448         } catch (SQLException JavaDoc sqlEx) {
449             checkAndFireConnectionError(sqlEx);
450         }
451     }
452
453     /* (non-Javadoc)
454      * @see java.sql.Statement#cancel()
455      */

456     public void cancel() throws SQLException JavaDoc {
457         try {
458             if (this.wrappedStmt != null) {
459                 this.wrappedStmt.cancel();
460             }
461         } catch (SQLException JavaDoc sqlEx) {
462             checkAndFireConnectionError(sqlEx);
463         }
464     }
465
466     /* (non-Javadoc)
467      * @see java.sql.Statement#clearBatch()
468      */

469     public void clearBatch() throws SQLException JavaDoc {
470         try {
471             if (this.wrappedStmt != null) {
472                 this.wrappedStmt.clearBatch();
473             }
474         } catch (SQLException JavaDoc sqlEx) {
475             checkAndFireConnectionError(sqlEx);
476         }
477     }
478
479     /* (non-Javadoc)
480      * @see java.sql.Statement#clearWarnings()
481      */

482     public void clearWarnings() throws SQLException JavaDoc {
483         try {
484             if (this.wrappedStmt != null) {
485                 this.wrappedStmt.clearWarnings();
486             }
487         } catch (SQLException JavaDoc sqlEx) {
488             checkAndFireConnectionError(sqlEx);
489         }
490     }
491
492     /* (non-Javadoc)
493      * @see java.sql.Statement#close()
494      */

495     public void close() throws SQLException JavaDoc {
496         try {
497             if (this.wrappedStmt != null) {
498                 this.wrappedStmt.close();
499             }
500         } catch (SQLException JavaDoc sqlEx) {
501             checkAndFireConnectionError(sqlEx);
502         } finally {
503             this.wrappedStmt = null;
504             this.pooledConnection = null;
505         }
506     }
507
508     /* (non-Javadoc)
509      * @see java.sql.Statement#execute(java.lang.String, int)
510      */

511     public boolean execute(String JavaDoc sql, int autoGeneratedKeys)
512         throws SQLException JavaDoc {
513         try {
514             if (this.wrappedStmt != null) {
515                 return this.wrappedStmt.execute(sql, autoGeneratedKeys);
516             } else {
517                 throw new SQLException JavaDoc("Statement already closed",
518                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
519             }
520         } catch (SQLException JavaDoc sqlEx) {
521             checkAndFireConnectionError(sqlEx);
522         }
523
524         return false; // we actually never get here, but the compiler can't figure
525

526         // that out
527
}
528
529     /* (non-Javadoc)
530      * @see java.sql.Statement#execute(java.lang.String, int[])
531      */

532     public boolean execute(String JavaDoc sql, int[] columnIndexes)
533         throws SQLException JavaDoc {
534         try {
535             if (this.wrappedStmt != null) {
536                 return this.wrappedStmt.execute(sql, columnIndexes);
537             } else {
538                 throw new SQLException JavaDoc("Statement already closed",
539                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
540             }
541         } catch (SQLException JavaDoc sqlEx) {
542             checkAndFireConnectionError(sqlEx);
543         }
544
545         return false; // we actually never get here, but the compiler can't figure
546

547         // that out
548
}
549
550     /* (non-Javadoc)
551      * @see java.sql.Statement#execute(java.lang.String, java.lang.String[])
552      */

553     public boolean execute(String JavaDoc sql, String JavaDoc[] columnNames)
554         throws SQLException JavaDoc {
555         try {
556             if (this.wrappedStmt != null) {
557                 return this.wrappedStmt.execute(sql, columnNames);
558             } else {
559                 throw new SQLException JavaDoc("Statement already closed",
560                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
561             }
562         } catch (SQLException JavaDoc sqlEx) {
563             checkAndFireConnectionError(sqlEx);
564         }
565
566         return false; // we actually never get here, but the compiler can't figure
567

568         // that out
569
}
570
571     /* (non-Javadoc)
572      * @see java.sql.Statement#execute(java.lang.String)
573      */

574     public boolean execute(String JavaDoc sql) throws SQLException JavaDoc {
575         try {
576             if (this.wrappedStmt != null) {
577                 return this.wrappedStmt.execute(sql);
578             } else {
579                 throw new SQLException JavaDoc("Statement already closed",
580                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
581             }
582         } catch (SQLException JavaDoc sqlEx) {
583             checkAndFireConnectionError(sqlEx);
584         }
585
586         return false; // we actually never get here, but the compiler can't figure
587

588         // that out
589
}
590
591     /* (non-Javadoc)
592      * @see java.sql.Statement#executeBatch()
593      */

594     public int[] executeBatch() throws SQLException JavaDoc {
595         try {
596             if (this.wrappedStmt != null) {
597                 return this.wrappedStmt.executeBatch();
598             } else {
599                 throw new SQLException JavaDoc("Statement already closed",
600                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
601             }
602         } catch (SQLException JavaDoc sqlEx) {
603             checkAndFireConnectionError(sqlEx);
604         }
605
606         return null; // we actually never get here, but the compiler can't figure
607

608         // that out
609
}
610
611     /* (non-Javadoc)
612      * @see java.sql.Statement#executeQuery(java.lang.String)
613      */

614     public ResultSet JavaDoc executeQuery(String JavaDoc sql) throws SQLException JavaDoc {
615         try {
616             if (this.wrappedStmt != null) {
617                 return this.wrappedStmt.executeQuery(sql);
618             } else {
619                 throw new SQLException JavaDoc("Statement already closed",
620                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
621             }
622         } catch (SQLException JavaDoc sqlEx) {
623             checkAndFireConnectionError(sqlEx);
624         }
625
626         return null; // we actually never get here, but the compiler can't figure
627

628         // that out
629
}
630
631     /* (non-Javadoc)
632      * @see java.sql.Statement#executeUpdate(java.lang.String, int)
633      */

634     public int executeUpdate(String JavaDoc sql, int autoGeneratedKeys)
635         throws SQLException JavaDoc {
636         try {
637             if (this.wrappedStmt != null) {
638                 return this.wrappedStmt.executeUpdate(sql, autoGeneratedKeys);
639             } else {
640                 throw new SQLException JavaDoc("Statement already closed",
641                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
642             }
643         } catch (SQLException JavaDoc sqlEx) {
644             checkAndFireConnectionError(sqlEx);
645         }
646
647         return -1; // we actually never get here, but the compiler can't figure
648

649         // that out
650
}
651
652     /* (non-Javadoc)
653      * @see java.sql.Statement#executeUpdate(java.lang.String, int[])
654      */

655     public int executeUpdate(String JavaDoc sql, int[] columnIndexes)
656         throws SQLException JavaDoc {
657         try {
658             if (this.wrappedStmt != null) {
659                 return this.wrappedStmt.executeUpdate(sql, columnIndexes);
660             } else {
661                 throw new SQLException JavaDoc("Statement already closed",
662                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
663             }
664         } catch (SQLException JavaDoc sqlEx) {
665             checkAndFireConnectionError(sqlEx);
666         }
667
668         return -1; // we actually never get here, but the compiler can't figure
669

670         // that out
671
}
672
673     /* (non-Javadoc)
674      * @see java.sql.Statement#executeUpdate(java.lang.String, java.lang.String[])
675      */

676     public int executeUpdate(String JavaDoc sql, String JavaDoc[] columnNames)
677         throws SQLException JavaDoc {
678         try {
679             if (this.wrappedStmt != null) {
680                 return this.wrappedStmt.executeUpdate(sql, columnNames);
681             } else {
682                 throw new SQLException JavaDoc("Statement already closed",
683                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
684             }
685         } catch (SQLException JavaDoc sqlEx) {
686             checkAndFireConnectionError(sqlEx);
687         }
688
689         return -1; // we actually never get here, but the compiler can't figure
690

691         // that out
692
}
693
694     /* (non-Javadoc)
695      * @see java.sql.Statement#executeUpdate(java.lang.String)
696      */

697     public int executeUpdate(String JavaDoc sql) throws SQLException JavaDoc {
698         try {
699             if (this.wrappedStmt != null) {
700                 return this.wrappedStmt.executeUpdate(sql);
701             } else {
702                 throw new SQLException JavaDoc("Statement already closed",
703                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
704             }
705         } catch (SQLException JavaDoc sqlEx) {
706             checkAndFireConnectionError(sqlEx);
707         }
708
709         return -1; // we actually never get here, but the compiler can't figure
710

711         // that out
712
}
713 }
714
Popular Tags