OSDN Git Service

new repository
[stew/Stew4.git] / src / net / argius / stew / Environment.java
1 package net.argius.stew;
2
3 import static net.argius.stew.Bootstrap.getDirectory;
4
5 import java.io.*;
6 import java.sql.*;
7
8 import net.argius.stew.ui.*;
9
10 /**
11  * Environment.
12  */
13 public final class Environment {
14
15     static final String CONNECTOR_PROPERTIES_NAME = "connector.properties";
16     static final String ALIAS_PROPERTIES_NAME = "alias.properties";
17
18     private static final Logger log = Logger.getLogger(Environment.class);
19     static ResourceManager res = ResourceManager.getInstance(Environment.class);
20
21     private OutputProcessor outputProcessor;
22     private ConnectorMap connectorMap;
23     private Connector connector;
24     private Connection conn;
25
26     private int timeoutSeconds;
27     private File systemDirectory;
28     private File currentDirectory;
29     private long connectorTimestamp;
30     private Alias alias;
31
32     /**
33      * A constructor.
34      */
35     public Environment() {
36         initializeQueryTimeout();
37         // init connections
38         this.connectorMap = new ConnectorMap();
39         loadConnectorMap();
40         // init directories
41         this.systemDirectory = getDirectory();
42         this.currentDirectory = getInitialCurrentDirectory();
43         // init alias
44         final File aliasPropFile = new File(this.systemDirectory, ALIAS_PROPERTIES_NAME);
45         this.alias = new Alias(aliasPropFile);
46         if (aliasPropFile.exists()) {
47             try {
48                 alias.load();
49             } catch (IOException ex) {
50                 log.warn(ex);
51             }
52         }
53     }
54
55     /**
56      * A constructor (for copy).
57      * @param src
58      */
59     public Environment(Environment src) {
60         // never copy coconnector,conn,op into this
61         this.connectorMap = new ConnectorMap(src.connectorMap);
62         this.timeoutSeconds = src.timeoutSeconds;
63         this.systemDirectory = src.systemDirectory;
64         this.currentDirectory = src.currentDirectory;
65     }
66
67     /**
68      * Releases resouces it keeps.
69      */
70     public void release() {
71         try {
72             releaseConnection();
73             log.debug("released connection");
74         } catch (SQLException ex) {
75             log.error(ex, "release error");
76         } finally {
77             outputProcessor = null;
78             connectorMap = null;
79             connector = null;
80             conn = null;
81             systemDirectory = null;
82             currentDirectory = null;
83         }
84         log.debug("released internal state of Environment");
85     }
86
87     /**
88      * Establishes a connection.
89      * @param connector
90      * @throws SQLException
91      */
92     void establishConnection(Connector connector) throws SQLException {
93         Connection conn = connector.getConnection();
94         try {
95             if (connector.isReadOnly()) {
96                 conn.setReadOnly(true);
97             }
98         } catch (RuntimeException ex) {
99             log.warn(ex);
100         }
101         boolean isAutoCommitAvailable;
102         try {
103             conn.setAutoCommit(false);
104             isAutoCommitAvailable = conn.getAutoCommit();
105         } catch (RuntimeException ex) {
106             log.warn(ex);
107             isAutoCommitAvailable = false;
108         }
109         if (isAutoCommitAvailable) {
110             outputMessage("w.auto-commit-not-available");
111         }
112         setCurrentConnection(conn);
113         setCurrentConnector(connector);
114         outputMessage("i.connected");
115         log.debug("connected %s (conn=%08x, env=%08x)", connector.getId(), conn.hashCode(), hashCode());
116         if (Bootstrap.getPropertyAsBoolean("net.argius.stew.print-connected-time")) {
117             outputMessage("i.now", System.currentTimeMillis());
118         }
119     }
120
121     /**
122      * Releases the connection.
123      * @throws SQLException
124      */
125     void releaseConnection() throws SQLException {
126         if (conn == null) {
127             log.debug("not connected");
128             return;
129         }
130         try {
131             if (connector != null && connector.usesAutoRollback()) {
132                 try {
133                     conn.rollback();
134                     outputMessage("i.rollbacked");
135                     log.debug("rollbacked %s (%s)", connector.getId(), conn);
136                 } catch (SQLException ex) {
137                     log.warn(ex);
138                 }
139             }
140             try {
141                 conn.close();
142                 log.debug("disconnected %s (conn=%08x, env=%08x)", connector.getId(), conn.hashCode(), hashCode());
143                 if (Bootstrap.getPropertyAsBoolean("net.argius.stew.print-disconnected-time")) {
144                     outputMessage("i.now", System.currentTimeMillis());
145                 }
146             } catch (SQLException ex) {
147                 log.warn(ex);
148                 throw ex;
149             }
150         } finally {
151             conn = null;
152             connector = null;
153         }
154     }
155
156     private void outputMessage(String id, Object... args) throws CommandException {
157         if (outputProcessor != null) {
158             outputProcessor.output(res.get(id, args));
159         }
160     }
161
162     private static File getInitialCurrentDirectory() {
163         final String propkey = "net.argius.stew.directory";
164         if (Bootstrap.hasProperty(propkey)) {
165             File directory = new File(Bootstrap.getProperty(propkey, ""));
166             if (directory.isDirectory()) {
167                 return directory;
168             }
169         }
170         return new File(".");
171     }
172
173     private void initializeQueryTimeout() {
174         this.timeoutSeconds = Bootstrap.getPropertyAsInt("net.argius.stew.query.timeout", -1);
175         if (log.isDebugEnabled()) {
176             log.debug("timeout: " + this.timeoutSeconds);
177         }
178     }
179
180     /**
181      * Loads and refreshes connector map.
182      */
183     public void loadConnectorMap() {
184         File connectorFile = new File(getDirectory(), CONNECTOR_PROPERTIES_NAME);
185         ConnectorMap m;
186         try {
187             InputStream is = new FileInputStream(connectorFile);
188             try {
189                 m = ConnectorConfiguration.load(is);
190             } finally {
191                 is.close();
192             }
193         } catch (IOException ex) {
194             m = new ConnectorMap();
195         }
196         synchronized (connectorMap) {
197             if (connectorMap.size() > 0) {
198                 connectorMap.clear();
199             }
200             connectorMap.putAll(m);
201             connectorTimestamp = connectorFile.lastModified();
202         }
203     }
204
205     /**
206      * Updates connector map.
207      * When file was updated, it calls loadConnectorMap().
208      * @return whether updated or not
209      */
210     public boolean updateConnectorMap() {
211         File connectorFile = new File(getDirectory(), CONNECTOR_PROPERTIES_NAME);
212         if (connectorFile.lastModified() > connectorTimestamp) {
213             loadConnectorMap();
214             return true;
215         }
216         return false;
217     }
218
219     public OutputProcessor getOutputProcessor() {
220         return outputProcessor;
221     }
222
223     public void setOutputProcessor(OutputProcessor outputProcessor) {
224         this.outputProcessor = outputProcessor;
225     }
226
227     public ConnectorMap getConnectorMap() {
228         return connectorMap;
229     }
230
231     public Connector getCurrentConnector() {
232         return connector;
233     }
234
235     void setCurrentConnector(Connector connector) {
236         this.connector = connector;
237     }
238
239     public Connection getCurrentConnection() {
240         return conn;
241     }
242
243     void setCurrentConnection(Connection conn) {
244         this.conn = conn;
245     }
246
247     public int getTimeoutSeconds() {
248         return timeoutSeconds;
249     }
250
251     public File getCurrentDirectory() {
252         return currentDirectory;
253     }
254
255     public void setCurrentDirectory(File currentDirectory) {
256         this.currentDirectory = currentDirectory;
257     }
258
259     public File getSystemDirectory() {
260         return systemDirectory;
261     }
262
263     public Alias getAlias() {
264         return alias;
265     }
266
267 }