OSDN Git Service

Upgrade to 4.2.0
[stew/Stew4.git] / src / net / argius / stew / Environment.java
1 package net.argius.stew;
2
3 import static net.argius.stew.Bootstrap.getSystemFile;
4
5 import java.io.*;
6 import java.sql.*;
7
8 import javax.script.*;
9
10 import net.argius.stew.ui.*;
11
12 /**
13  * Environment.
14  */
15 public final class Environment {
16
17     static final String ALIAS_PROPERTIES_NAME = "alias.properties";
18
19     private static final Logger log = Logger.getLogger(Environment.class);
20     static ResourceManager res = ResourceManager.getInstance(Environment.class);
21
22     private OutputProcessor outputProcessor;
23     private ConnectorMap connectorMap;
24     private Connector connector;
25     private Connection conn;
26
27     private int timeoutSeconds;
28     private File currentDirectory;
29     private long connectorTimestamp;
30     private AliasMap aliasMap;
31     private ScriptContext scriptContext;
32
33     private Environment(ConnectorMap connectorMap, File currentDirectory) {
34         this.connectorMap = connectorMap;
35         this.currentDirectory = currentDirectory;
36         // init alias
37         final File aliasPropFile = getSystemFile(ALIAS_PROPERTIES_NAME);
38         this.aliasMap = new AliasMap(aliasPropFile);
39         if (aliasPropFile.exists()) {
40             try {
41                 aliasMap.load();
42             } catch (IOException ex) {
43                 log.warn(ex);
44             }
45         }
46     }
47
48     /**
49      * A constructor.
50      */
51     public Environment() {
52         this(new ConnectorMap(), getInitialCurrentDirectory()); // init directories
53         initializeQueryTimeout();
54         loadConnectorMap();
55         initializeScriptContext();
56     }
57
58     /**
59      * A constructor (for copy).
60      * @param src
61      */
62     public Environment(Environment src) {
63         // never copy coconnector,conn,op,aliasMap,scriptContext into this
64         this(new ConnectorMap(src.connectorMap), src.currentDirectory);
65         this.timeoutSeconds = src.timeoutSeconds;
66     }
67
68     /**
69      * Releases resouces it keeps.
70      */
71     public void release() {
72         try {
73             releaseConnection();
74             log.debug("released connection");
75         } catch (SQLException ex) {
76             log.error(ex, "release error");
77         } finally {
78             outputProcessor = null;
79             connectorMap = null;
80             connector = null;
81             conn = 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                     Writer w = new StringWriter();
139                     PrintWriter out = new PrintWriter(w);
140                     ex.printStackTrace(out);
141                     outputMessage("e.database", w);
142                     outputMessage("w.error-occurred-on-auto-rollback", ex);
143                 }
144             }
145             try {
146                 conn.close();
147                 if (log.isDebugEnabled()) {
148                     final String id = (connector == null) ? "null" : connector.getId();
149                     log.debug("disconnected %s (conn=%08x, env=%08x)", id, conn.hashCode(), hashCode());
150                 }
151                 if (Bootstrap.getPropertyAsBoolean("net.argius.stew.print-disconnected-time")) {
152                     outputMessage("i.now", System.currentTimeMillis());
153                 }
154             } catch (SQLException ex) {
155                 log.warn(ex);
156                 throw ex;
157             }
158         } finally {
159             conn = null;
160             connector = null;
161         }
162     }
163
164     private void outputMessage(String id, Object... args) throws CommandException {
165         if (outputProcessor != null) {
166             outputProcessor.output(res.get(id, args));
167         }
168     }
169
170     private static File getInitialCurrentDirectory() {
171         final String propkey = "net.argius.stew.directory";
172         if (Bootstrap.hasProperty(propkey)) {
173             File directory = new File(Bootstrap.getProperty(propkey, ""));
174             if (directory.isDirectory()) {
175                 return directory;
176             }
177         }
178         return new File(".");
179     }
180
181     private void initializeQueryTimeout() {
182         this.timeoutSeconds = Bootstrap.getPropertyAsInt("net.argius.stew.query.timeout", -1);
183         if (log.isDebugEnabled()) {
184             log.debug("timeout: " + this.timeoutSeconds);
185         }
186     }
187
188     void initializeScriptContext() {
189         this.scriptContext = new SimpleScriptContext();
190     }
191
192     /**
193      * Loads and refreshes connector map.
194      */
195     public void loadConnectorMap() {
196         ConnectorMap m;
197         try {
198             m = ConnectorConfiguration.load();
199         } catch (IOException ex) {
200             m = new ConnectorMap();
201         }
202         synchronized (connectorMap) {
203             if (connectorMap.size() > 0) {
204                 connectorMap.clear();
205             }
206             connectorMap.putAll(m);
207             connectorTimestamp = ConnectorConfiguration.lastModified();
208         }
209     }
210
211     /**
212      * Updates connector map.
213      * When file was updated, it calls loadConnectorMap().
214      * @return whether updated or not
215      */
216     public boolean updateConnectorMap() {
217         if (ConnectorConfiguration.lastModified() > connectorTimestamp) {
218             loadConnectorMap();
219             return true;
220         }
221         return false;
222     }
223
224     public OutputProcessor getOutputProcessor() {
225         return outputProcessor;
226     }
227
228     public void setOutputProcessor(OutputProcessor outputProcessor) {
229         this.outputProcessor = outputProcessor;
230     }
231
232     public ConnectorMap getConnectorMap() {
233         return connectorMap;
234     }
235
236     public Connector getCurrentConnector() {
237         return connector;
238     }
239
240     void setCurrentConnector(Connector connector) {
241         this.connector = connector;
242     }
243
244     public Connection getCurrentConnection() {
245         return conn;
246     }
247
248     void setCurrentConnection(Connection conn) {
249         this.conn = conn;
250     }
251
252     public int getTimeoutSeconds() {
253         return timeoutSeconds;
254     }
255
256     public File getCurrentDirectory() {
257         return currentDirectory;
258     }
259
260     public void setCurrentDirectory(File currentDirectory) {
261         this.currentDirectory = currentDirectory;
262     }
263
264     /**
265      * @return system directory
266      * @deprecated use Bootstrap.getSystemDirectory() instead
267      */
268     @Deprecated
269     public File getSystemDirectory() {
270         return Bootstrap.getSystemDirectory();
271     }
272
273     public AliasMap getAliasMap() {
274         return aliasMap;
275     }
276
277     public ScriptContext getScriptContext() {
278         return scriptContext;
279     }
280
281 }