001/*
002 * Copyright (c) 2006-2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: crawl $'
006 * '$Date: 2015-02-02 20:09:20 +0000 (Mon, 02 Feb 2015) $' 
007 * '$Revision: 33217 $'
008 * 
009 * Permission is hereby granted, without written agreement and without
010 * license or royalty fees, to use, copy, modify, and distribute this
011 * software and its documentation for any purpose, provided that the above
012 * copyright notice and the following two paragraphs appear in all copies
013 * of this software.
014 *
015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
019 * SUCH DAMAGE.
020 *
021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
026 * ENHANCEMENTS, OR MODIFICATIONS.
027 *
028 */
029
030package org.kepler.gui;
031
032import java.io.File;
033import java.io.FileNotFoundException;
034import java.io.FileOutputStream;
035import java.io.PrintStream;
036import java.sql.Connection;
037import java.sql.PreparedStatement;
038import java.sql.ResultSet;
039import java.sql.Statement;
040import java.util.Iterator;
041import java.util.List;
042import java.util.concurrent.Executors;
043import java.util.concurrent.TimeUnit;
044import java.util.regex.Matcher;
045import java.util.regex.Pattern;
046
047import org.apache.commons.logging.Log;
048import org.apache.commons.logging.LogFactory;
049import org.ecoinformatics.seek.ecogrid.SearchRegistryAction;
050import org.geon.DBConnectionToken;
051import org.kepler.configuration.ConfigurationManager;
052import org.kepler.configuration.ConfigurationProperty;
053import org.kepler.objectmanager.cache.CacheManager;
054import org.kepler.objectmanager.cache.LocalRepositoryManager;
055import org.kepler.util.AuthNamespace;
056import org.kepler.util.DotKeplerManager;
057import org.kepler.util.sql.DatabaseFactory;
058
059import ptolemy.actor.gui.Configuration;
060import ptolemy.data.expr.Constants;
061import ptolemy.gui.Top;
062import ptolemy.kernel.util.StringAttribute;
063import ptolemy.moml.MoMLParser;
064import ptolemy.util.StringUtilities;
065
066//////////////////////////////////////////////////////////////////////////
067//// KeplerInitializer
068
069/**
070 * Initialize Kepler.
071 * 
072 * <p>
073 * How this works is that configs/ptolemy/configs/kepler/configuration.xml sets
074 * a StringParameter called "_applicationInitializer" that names this class.
075 * KeplerApplication reads the parameter and instantiates this class.
076 * 
077 * @author Kevin Ruland
078 * @version $Id: KeplerInitializer.java 33217 2015-02-02 20:09:20Z crawl $
079 * @since Ptolemy II 6.0
080 * @Pt.ProposedRating Red (cxh)
081 * @Pt.AcceptedRating Red (cxh)
082 */
083public class KeplerInitializer {
084
085        private static Log log = LogFactory
086                        .getLog("org.kepler.gui.KeplerInitialization");
087        private static boolean hasBeenInitialized = false;
088
089        // redirects standard out and err streams
090        private static boolean log_file = false;
091
092        private static boolean autoUpdate;
093
094        private static int autoUpdateDelay;
095
096        /** Perform any Kepler specific initialization. */
097        public KeplerInitializer() throws Exception {
098                initializeSystem();
099        }
100
101        public static void initializeSystem() throws Exception {
102                System.out.println("Kepler Initializing...");
103                // Only run initialization once.
104                if (hasBeenInitialized) {
105                        return;
106                }
107
108                hasBeenInitialized = true;
109
110                ConfigurationProperty commonProperty = ConfigurationManager
111                                .getInstance().getProperty(
112                                                ConfigurationManager.getModule("common"));
113
114                autoUpdate = Boolean.parseBoolean(commonProperty.getProperty(
115                                "autoDataSourcesUpdate.value").getValue());
116                autoUpdateDelay = Integer.parseInt(commonProperty.getProperty(
117                                "autoDataSourcesUpdate.delay").getValue());
118
119                // Add the dbconnection type.
120                Constants.add("dbconnection", new DBConnectionToken());
121
122                DotKeplerManager dkm = DotKeplerManager.getInstance();
123
124                // String log_file_setting = c.getValue("//log_file");
125                String log_file_setting = commonProperty.getProperty("log_file")
126                                .getValue();
127
128                if (log_file_setting != null) {
129                        if (log_file_setting.equalsIgnoreCase("true")) {
130                                log_file = true;
131                        } else {
132                                log_file = false;
133                        }
134                }
135                if (log_file) {
136                        try {
137                                FileOutputStream err = new FileOutputStream("kepler_stderr.log");
138                                PrintStream errPrintStream = new PrintStream(err);
139                                System.setErr(errPrintStream);
140                                System.setOut(errPrintStream);
141                        } catch (FileNotFoundException fnfe) {
142                                System.out
143                                                .println("Warning: Failure to redirect log to a file.");
144                        }
145                }
146
147                // First get the entries named mkdir. We will make
148                // directories for each of these entries under the UserDir.
149
150                List mkdirList = commonProperty.getProperties("startup");
151                List mkdirs = ConfigurationProperty.getValueList(mkdirList, "mkdir",
152                                true);
153
154                for (Iterator i = mkdirs.iterator(); i.hasNext();) {
155                        String dir = (String) i.next();
156                        if (dir == null || dir.length() == 0) {
157                                continue;
158                        }
159
160                        dir = dkm.getCacheDir(dir);
161
162                        File f = new File(dir);
163                        if (!f.exists()) {
164                                boolean created = f.mkdirs();
165                                if (created) {
166                                        log.debug("Making directory " + dir);
167                                }
168                        }
169                }
170
171                Connection conn = DatabaseFactory.getDBConnection();
172                
173                //
174                // Get the tabletestsql entry. This is the sql used to test if a
175                // table already exists in the database.
176                //
177                String tabletestsql = commonProperty
178                                .getProperty("startup.tabletestsql").getValue();
179                PreparedStatement tabletest = null;
180                if (tabletestsql != null) {
181                        tabletest = conn.prepareStatement(tabletestsql);
182                }
183
184                // We use pattern matching to extract the tablename from the
185                // ddl statement. This is a Java 1.4 regex regular expression
186                // which extracts the word after the string "table". The
187                // match is case insensitive so "table" will also match
188                // "TABLE". The "(" ")" characters denote a grouping. This
189                // will be returned as group 1.
190
191                Pattern extractTable = Pattern.compile("table\\s+(\\w*)",
192                                Pattern.CASE_INSENSITIVE);
193
194                // Get the list of ddl statements defining the tables to create.
195                List createTableList = commonProperty.getProperties("startup");
196                List createtables = ConfigurationProperty.getValueList(createTableList,
197                                "createtable", true);
198
199                final String schemaName = CacheManager.getDatabaseSchemaName();
200                
201                for (Iterator i = createtables.iterator(); i.hasNext();) {
202                        String ddl = (String) i.next();
203                        // Create our Matcher object for the ddl string.
204                        Matcher m = extractTable.matcher(ddl);
205                        // Matcher.find() looks for any match of the pattern in the string.
206                        m.find();
207
208                        String tablename = m.group(1);
209                        if (tabletest == null) {
210                                log.error("unable to test for table: " + tablename);
211                                continue;
212                        }
213
214                        tabletest.setString(1, tablename);
215                        tabletest.setString(2, schemaName);
216                        ResultSet rs = tabletest.executeQuery();
217                        if (rs.next()) {
218                                log.debug("Table " + tablename + " already exists");
219                                continue;
220                        }
221                        Statement statement = conn.createStatement();
222                        statement.execute(ddl);
223                        statement.close();
224                        log.debug("Table " + tablename + " created");
225                }
226                tabletest.close();
227
228                // Get the Authorized Namespace after the tables are set up.
229                AuthNamespace an = AuthNamespace.getInstance();
230                an.initialize();
231
232                // Hook to execute arbitrary sql statements on the internal database.
233                // List sqls = c.getList("//startup/sql");
234                List sqlList = commonProperty.getProperties("startup");
235                List sqls = ConfigurationProperty.getValueList(sqlList, "sql", true);
236                Statement statement = null;
237                for (Iterator i = sqls.iterator(); i.hasNext();) {
238                        String statementStr = (String) i.next();
239                        log.info("Executing sql command " + statementStr);
240                        statement = conn.createStatement();
241                        statement.execute(statementStr);                        
242                }
243                if (statement != null)
244                        statement.close();
245                conn.close();
246
247                // Set the icon loader to load Kepler files
248                MoMLParser.setIconLoader(new KeplerIconLoader());
249
250                // set the initial directory for file dialogs
251                setDefaultFileDialogDir();
252
253                // refresh the datasources from the registry
254                updateDataSources();
255        }
256
257        private static void updateDataSources() {
258                if (autoUpdate) {
259                        Executors.newSingleThreadScheduledExecutor().schedule(
260                                        new Runnable() {
261                                                public void run() {
262                                                        SearchRegistryAction.queryRegistryRewriteConfig();
263                                                }
264                                        }, autoUpdateDelay, TimeUnit.SECONDS);
265                }
266        }
267
268        /** Set the default directory used for open and save dialogs. Use
269         *  _alternateDefaultOpenDirectory is set. Otherwise, use the
270         *  default local save repository (MyWorkflows).
271         * 
272         */
273        private static void setDefaultFileDialogDir() {
274                boolean wasSet = false;
275
276                String currentWorkingDirectory;
277                List configsList = Configuration.configurations();
278                Configuration config = null;
279                Object object = null;
280                for (Iterator it = configsList.iterator(); it.hasNext();) {
281                        config = (Configuration) it.next();
282                        if (config != null) {
283                                break;
284                        }
285                }
286
287                // see if _alternateDefaultOpenDirectory is set
288
289                if (config != null) {
290                        StringAttribute alternateDefaultOpenDirAttribute = (StringAttribute) config
291                                        .getAttribute("_alternateDefaultOpenDirectory");
292                        if (alternateDefaultOpenDirAttribute != null) {
293                                final String altDirStr = alternateDefaultOpenDirAttribute
294                                                .getExpression();
295                                final File altDirFile = new File(altDirStr);
296
297                                // see if the alternate directory is absolute and exists
298                                if(altDirFile.isAbsolute() && altDirFile.isDirectory()) {
299                                        Top.setDirectory(altDirFile);
300                                        wasSet = true;
301                                } else if(!altDirFile.isAbsolute()) {
302                                
303                                        // it was not absolute, so put prepend the Kepler directory
304                                        currentWorkingDirectory = StringUtilities
305                                                .getProperty("KEPLER");
306                                        if (currentWorkingDirectory != null) {
307                                                File dir = new File(currentWorkingDirectory,
308                                                                altDirStr);
309                                                if (dir != null && dir.isDirectory()) {
310                                                        Top.setDirectory(dir);
311                                                        wasSet = true;
312                                                }
313                                        }
314                                }
315                        }
316                }
317
318                // if we did set it, use the default save repository
319                if (!wasSet) {
320                        File saveRepo = LocalRepositoryManager.getInstance().getSaveRepository();
321                        if (saveRepo != null && saveRepo.isDirectory()){
322                                Top.setDirectory(saveRepo);
323                        }
324                }
325        }
326}