001    package railo.runtime.db;
002    
003    
004    import java.sql.Connection;
005    import java.sql.SQLException;
006    
007    import railo.runtime.PageContext;
008    import railo.runtime.PageContextImpl;
009    import railo.runtime.config.ConfigImpl;
010    import railo.runtime.engine.ThreadLocalPageContext;
011    import railo.runtime.exp.DatabaseException;
012    import railo.runtime.exp.ExceptionHandler;
013    import railo.runtime.exp.PageException;
014    import railo.runtime.orm.ORMDatasourceConnection;
015    import railo.runtime.orm.ORMSession;
016    
017    /**
018     * this class handle multible db connection, transaction and logging
019     */
020    public final class DatasourceManagerImpl implements DataSourceManager {
021            
022            private ConfigImpl config;
023            
024            boolean autoCommit=true;
025            private int isolation=Connection.TRANSACTION_NONE;
026            private DatasourceConnection transConn;
027        
028    
029            /**
030             * constructor of the class
031             * @param pc
032             */
033            public DatasourceManagerImpl(ConfigImpl c) {
034                    this.config=c;
035            }
036    
037            /**
038             * FUTURE deprecated
039             * @see DataSourceManager#getConnection(PageContext pc,java.lang.String, java.lang.String, java.lang.String)
040             */
041            public DatasourceConnection getConnection(PageContext pc,String _datasource, String user, String pass) throws PageException {
042                    return getConnection(pc,pc.getConfig().getDataSource(_datasource), user, pass);
043            }
044    
045            // FUTURE add to interface
046            public DatasourceConnection getConnection(PageContext pc,DataSource ds, String user, String pass) throws PageException {
047                    if(autoCommit)
048                            return config.getDatasourceConnectionPool().getDatasourceConnection(pc,ds,user,pass);
049                    
050                    
051                    pc=ThreadLocalPageContext.get(pc);
052                    DatasourceConnection dc=((PageContextImpl)pc)._getConnection(ds,user,pass);
053                    
054                    // transaction
055                    //if(!autoCommit) {
056                try {
057                    if(transConn==null) {
058                            dc.getConnection().setAutoCommit(false);
059                                            
060                        if(isolation!=Connection.TRANSACTION_NONE)
061                                                dc.getConnection().setTransactionIsolation(isolation);
062                        transConn=dc;
063                            }
064                            else if(!transConn.equals(dc)) {
065                            if("_queryofquerydb".equalsIgnoreCase(ds.getName())) return dc;
066                                    throw new DatabaseException(
067                                                    "can't use different connections inside a transaction",null,null,dc);
068                            }
069                    else if(dc.getConnection().getAutoCommit()) {
070                        dc.getConnection().setAutoCommit(false);
071                    }
072                } catch (SQLException e) {
073                   ExceptionHandler.printStackTrace(e);
074                }
075                    //}
076                    return dc;
077            }
078            
079    
080            public void add(PageContext pc,ORMSession session) throws PageException {
081                    
082                    // transaction
083                    if(!autoCommit) {
084                try {
085                    if(transConn==null) {
086                            ORMDatasourceConnection dc=new ORMDatasourceConnection(pc,session);
087                            
088                        if(isolation!=Connection.TRANSACTION_NONE)
089                                                dc.getConnection().setTransactionIsolation(isolation);
090                        transConn=dc;
091                            }
092                            else if(!(transConn instanceof ORMDatasourceConnection)){
093                                    /*if(transConn.getDatasource().equals(session.getEngine().getDataSource())){
094                                            ORMDatasourceConnection dc=new ORMDatasourceConnection(pc,session);
095                            
096                            if(isolation!=Connection.TRANSACTION_NONE)
097                                                dc.getConnection().setTransactionIsolation(isolation);
098                            transConn=dc;
099                                    }
100                                    else*/
101                                            throw new DatabaseException(
102                                                    "can't use transaction for datasource and orm at the same time",null,null,null);
103                            }
104                } catch (SQLException e) {
105                   ExceptionHandler.printStackTrace(e);
106                }
107                    }
108            }
109            
110            /**
111             * @see railo.runtime.db.DataSourceManager#releaseConnection(railo.runtime.db.DatasourceConnection)
112             */
113            public void releaseConnection(PageContext pc,DatasourceConnection dc) {
114                    if(autoCommit) config.getDatasourceConnectionPool().releaseDatasourceConnection(dc);
115            }
116            
117            /*private void releaseConnection(int pid,DatasourceConnection dc) {
118                    config.getDatasourceConnectionPool().releaseDatasourceConnection(pid,dc);
119            }*/
120            
121            /**
122             *
123             * @see DataSourceManager#begin()
124             */
125            public void begin() {
126                    this.autoCommit=false;
127                    this.isolation=Connection.TRANSACTION_NONE;             
128            }
129            
130            /**
131             *
132             * @see DataSourceManager#begin(java.lang.String)
133             */
134            public void begin(String isolation) {
135                    this.autoCommit=false;
136            
137                    if(isolation.equalsIgnoreCase("read_uncommitted"))
138                        this.isolation=Connection.TRANSACTION_READ_UNCOMMITTED;
139                    else if(isolation.equalsIgnoreCase("read_committed"))
140                        this.isolation=Connection.TRANSACTION_READ_COMMITTED;
141                    else if(isolation.equalsIgnoreCase("repeatable_read"))
142                        this.isolation=Connection.TRANSACTION_REPEATABLE_READ;
143                    else if(isolation.equalsIgnoreCase("serializable"))
144                        this.isolation=Connection.TRANSACTION_SERIALIZABLE;
145                    else 
146                        this.isolation=Connection.TRANSACTION_NONE;
147            
148            }
149        /**
150             *
151             * @see DataSourceManager#begin(int)
152             */
153        public void begin(int isolation) {
154            //print.out("begin:"+autoCommit);
155            this.autoCommit=false;
156            this.isolation=isolation;
157        }
158    
159            /**
160             *
161             * @see DataSourceManager#rollback()
162             */
163            public void rollback() throws DatabaseException {
164                    if(autoCommit)return;
165            //autoCommit=true;
166                    if(transConn!=null) {
167                            try {
168                                    transConn.getConnection().rollback();
169                                    //transConn.setAutoCommit(true);
170                            } 
171                            catch (SQLException e) {
172                                    throw new DatabaseException(e,transConn);
173                            }
174                            //transConn=null;
175                    }
176            }
177            
178            // FUTURE add to interface
179            public void savepoint() throws DatabaseException {
180                    if(autoCommit)return;
181            //autoCommit=true;
182                    if(transConn!=null) {
183                            try {
184                                    transConn.getConnection().setSavepoint();
185                            } 
186                            catch (SQLException e) {
187                                    throw new DatabaseException(e,transConn);
188                            }
189                    }
190            }
191    
192            /**
193             *
194             * @see DataSourceManager#commit()
195             */
196            public void commit() throws DatabaseException {
197            //print.out("commit:"+autoCommit);
198            if(autoCommit)return ;
199            //autoCommit=true;
200                    if(transConn!=null) {
201                            try {
202                                    transConn.getConnection().commit();
203                                    //transConn.setAutoCommit(true);
204                            } 
205                            catch (SQLException e) {
206                                    throw new DatabaseException(e,transConn);
207                            }
208                            //transConn=null;
209                    }
210            }
211            
212        /**
213             *
214             * @see DataSourceManager#isAutoCommit()
215             */
216        public boolean isAutoCommit() {
217            return autoCommit;
218        }
219    
220        /**
221             *
222             * @see DataSourceManager#end()
223             */
224        public void end() {
225            autoCommit=true;
226            if(transConn!=null) {
227                    try {
228                    transConn.getConnection().setAutoCommit(true);
229                } 
230                catch (SQLException e) {
231                    ExceptionHandler.printStackTrace(e);
232                }
233                transConn=null;
234            }
235        }
236    
237            public void remove(String datasource) {
238                    config.getDatasourceConnectionPool().remove(datasource);
239            }
240    
241            public void release() {
242                    this.transConn=null;
243                    this.isolation=Connection.TRANSACTION_NONE;
244            }
245    
246    }