001    /*
002     * $Id: ArgumentManager.java,v 1.23 2012/04/30 20:48:16 jbeavers Exp $
003     *
004     * This file is part of McIDAS-V
005     *
006     * Copyright 2007-2012
007     * Space Science and Engineering Center (SSEC)
008     * University of Wisconsin - Madison
009     * 1225 W. Dayton Street, Madison, WI 53706, USA
010     * https://www.ssec.wisc.edu/mcidas
011     * 
012     * All Rights Reserved
013     * 
014     * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
015     * some McIDAS-V source code is based on IDV and VisAD source code.  
016     * 
017     * McIDAS-V is free software; you can redistribute it and/or modify
018     * it under the terms of the GNU Lesser Public License as published by
019     * the Free Software Foundation; either version 3 of the License, or
020     * (at your option) any later version.
021     * 
022     * McIDAS-V is distributed in the hope that it will be useful,
023     * but WITHOUT ANY WARRANTY; without even the implied warranty of
024     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
025     * GNU Lesser Public License for more details.
026     * 
027     * You should have received a copy of the GNU Lesser Public License
028     * along with this program.  If not, see http://www.gnu.org/licenses.
029     */
030    
031    package edu.wisc.ssec.mcidasv;
032    
033    import java.util.ArrayList;
034    import java.util.Collections;
035    import java.util.List;
036    
037    import edu.wisc.ssec.mcidasv.startupmanager.StartupManager;
038    
039    import ucar.unidata.idv.ArgsManager;
040    import ucar.unidata.idv.IntegratedDataViewer;
041    import ucar.unidata.util.IOUtil;
042    import ucar.unidata.util.LogUtil;
043    import ucar.unidata.util.PatternFileFilter;
044    
045    /**
046     * McIDAS-V needs to handle a few command line flags/options that the IDV does
047     * not. Only the ability to force the Aqua look and feel currently exists.
048     * 
049     * @author McIDAS-V Developers
050     */
051    public class ArgumentManager extends ArgsManager {
052    
053        /** usage message */
054        public static final String USAGE_MESSAGE =
055            "Usage: runMcV [OPTIONS] <bundle/script files, e.g., .mcv, .mcvz, .py>";
056    
057        /**
058         *  Given by the "-user" argument. Alternative user path for bundles,  resources, etc.
059         */
060        String defaultUserDirectory = StartupManager.INSTANCE.getPlatform().getUserDirectory();
061    
062        /**
063         * Just bubblin' on up the inheritance hierarchy.
064         * 
065         * @param idv The IDV instance.
066         * @param args The command line arguments that were given.
067         */
068        public ArgumentManager(IntegratedDataViewer idv, String[] args) {
069            super(idv, args);
070        }
071    
072        /**
073         * Currently we're only handling the {@code -forceaqua} flag so we can
074         * mitigate some overlay issues we've been seeing on OS X Leopard.
075         * 
076         * @param arg The current argument we're examining.
077         * @param args The actual array of arguments.
078         * @param idx The index of {@code arg} within {@code args}.
079         * 
080         * @return The idx of the last value in the args array we look at. i.e., 
081         * if the flag arg does not require any further values in the args array 
082         * then don't increment idx.  If arg requires one more value then 
083         * increment idx by one. etc.
084         * 
085         * @throws Exception Throw bad things off to something that can handle 'em!
086         */
087        protected int parseArg(String arg, String[] args, int idx) 
088            throws Exception {
089    
090            if ("-forceaqua".equals(arg)) {
091                // unfortunately we can't simply set the look and feel here. If I
092                // were to do so, the loadLookAndFeel in the IdvUIManager would 
093                // eventually get loaded and then set the look and feel to whatever
094                // the preferences dictate.
095                // instead I use the boolean toggle to signal to McV's 
096                // UIManager.loadLookAndFeel that it should simply ignore the user's
097                // preference is and load the Aqua L&F from there.
098                McIDASV.useAquaLookAndFeel = true;
099            } else if (ARG_HELP.equals(arg)) {
100                System.err.println(USAGE_MESSAGE);
101                System.err.println(getUsageMessage());
102                ((McIDASV)getIdv()).exit(1);
103            } else if (checkArg(arg, "-script", args, idx, 1) || checkArg(arg, "-pyfile", args, idx, 1)) {
104                scriptingFiles.add(args[idx++]);
105                if (!getIslInteractive()) {
106                    setIsOffScreen(true);
107                }
108            } else {
109                if (ARG_ISLINTERACTIVE.equals(arg) || ARG_B64ISL.equals(arg) || ARG_ISLFILE.equals(arg) || isIslFile(arg)) {
110                    System.err.println("*** WARNING: ISL is being deprecated!");
111                }
112                return super.parseArg(arg, args, idx);
113            }
114            return idx;
115        }
116    
117        /**
118         * Print out the command line usage message and exit
119         * 
120         * @param err The usage message
121         */
122        @Override public void usage(String err) {
123            String msg = USAGE_MESSAGE;
124            msg = msg + '\n' + getUsageMessage();
125            LogUtil.userErrorMessage(err + '\n' + msg);
126            ((McIDASV)getIdv()).exit(1);
127        }
128    
129        /**
130         * Append some McIDAS-V specific command line options to the default IDV
131         * usage message.
132         *
133         * @return Usage message.
134         */
135        protected String getUsageMessage() {
136            return msg(ARG_HELP, "(this message)")
137                + msg("-forceaqua", "Forces the Aqua look and feel on OS X")
138                + msg(ARG_PROPERTIES, "<property file>")
139                + msg("-Dpropertyname=value", "(Define the property value)")
140                + msg(ARG_INSTALLPLUGIN, "<plugin jar file or url to install>")
141                + msg(ARG_PLUGIN, "<plugin jar file, directory, url for this run>")
142                + msg(ARG_NOPLUGINS, "Don't load plugins")
143                + msg(ARG_CLEARDEFAULT, "(Clear the default bundle)")
144                + msg(ARG_NODEFAULT, "(Don't read in the default bundle file)")
145                + msg(ARG_DEFAULT, "<.mcv/.mcvz file>")
146                + msg(ARG_BUNDLE, "<bundle file or url>")
147                + msg(ARG_B64BUNDLE, "<base 64 encoded inline bundle>")
148                + msg(ARG_SETFILES, "<datasource pattern> <semi-colon delimited list of files> (Use the list of files for the bundled datasource)")
149                + msg(ARG_ONEINSTANCEPORT, "<port number> (Check if another version of McIDAS-V is running. If so pass command line arguments to it and shutdown)")
150                + msg(ARG_NOONEINSTANCE, "(Don't do the one instance port)")
151                + msg(ARG_NOPREF, "(Don't read in the user preferences)")
152                + msg(ARG_USERPATH, "<user directory to use>")
153                + msg(ARG_SITEPATH, "<url path to find site resources>")
154                + msg(ARG_NOGUI, "(Don't show the main window gui)")
155                + msg(ARG_DATA, "<data source> (Load the data source)")
156                + msg(ARG_DISPLAY, "<parameter> <display>")
157    //            + msg("<scriptfile.isl>", "(Run the IDV script in batch mode)")
158                + msg("-script", "<jython script file to evaluate>")
159                + msg("-pyfile", "<jython script file to evaluate>")
160    //            + msg(ARG_B64ISL, "<base64 encoded inline isl> This will run the isl in interactive mode")
161    //            + msg(ARG_ISLINTERACTIVE, "run any isl files in interactive mode")
162                + msg(ARG_IMAGE, "<image file name> (create a jpeg image and then exit)")
163                + msg(ARG_MOVIE, "<movie file name> (create a quicktime movie and then exit)")
164                + msg(ARG_IMAGESERVER, "<port number or .properties file> (run McIDAS-V in image generation server mode. Support http requests on the given port)")
165                + msg(ARG_CATALOG, "<url to a chooser catalog>")
166                + msg(ARG_CONNECT, "<collaboration hostname to connect to>")
167                + msg(ARG_SERVER, "(Should McIDAS-V run in collaboration server mode)")
168                + msg(ARG_PORT, "<Port number collaboration server should listen on>")
169                + msg(ARG_CHOOSER, "(show the data chooser on start up) ")
170                + msg(ARG_PRINTJNLP, "(Print out any embedded bundles from jnlp files)")
171                + msg(ARG_CURRENTTIME, "<dttm> (Override current time for background processing)")
172    //            + msg(ARG_CURRENTTIME, "<dttm> (Override current time for ISL processing)")
173                + msg(ARG_LISTRESOURCES, "<list out the resource types")
174                + msg(ARG_DEBUG, "(Turn on debug print)")
175                + msg(ARG_MSG_DEBUG, "(Turn on language pack debug)")
176                + msg(ARG_MSG_RECORD, "<Language pack file to write missing entries to>")
177                + msg(ARG_TRACE, "(Print out trace messages)")
178                + msg(ARG_NOERRORSINGUI, "(Don't show errors in gui)")
179                + msg(ARG_TRACEONLY, "<trace pattern> (Print out trace messages that match the pattern)");
180        }
181    
182        /**
183         * @see ArgsManager#getBundleFileFilters()
184         */
185        @Override public List<PatternFileFilter> getBundleFileFilters() {
186            List<PatternFileFilter> filters = new ArrayList<PatternFileFilter>(); 
187            Collections.addAll(filters, getXidvFileFilter(), getZidvFileFilter(), FILTER_JNLP, FILTER_ISL, super.getXidvFileFilter(), super.getZidvFileFilter());
188            return filters;
189        }
190    
191        /**
192         * Returns a list of {@link PatternFileFilter}s that can be used to determine
193         * if a file is a bundle. 
194         * 
195         * <p>If {@code fromOpen} is {@code true}, the 
196         * returned list will contain {@code PatternFileFilter}s for bundles as 
197         * well as JNLP and ISL files. If {@code false}, the returned list will
198         * only contain filters for XML and zipped bundles.
199         * 
200         * @param fromOpen Whether or not this has been called from an 
201         * {@literal "open file"} dialog. 
202         * 
203         * @return Filters for bundles.
204         */
205        public List<PatternFileFilter> getBundleFilters(final boolean fromOpen) {
206            List<PatternFileFilter> filters = new ArrayList<PatternFileFilter>();
207    
208            if (fromOpen)
209                Collections.addAll(filters, getXidvZidvFileFilter(), FILTER_JNLP, FILTER_ISL, super.getXidvZidvFileFilter());
210            else
211                filters.addAll(getBundleFileFilters());
212    
213            return filters;
214        }
215    
216        /**
217         * @see ArgsManager#getXidvFileFilter()
218         */
219        @Override public PatternFileFilter getXidvFileFilter() {
220            return Constants.FILTER_MCV;
221        }
222    
223        /**
224         * @see ArgsManager#getZidvFileFilter()
225         */
226        @Override public PatternFileFilter getZidvFileFilter() {
227            return Constants.FILTER_MCVZ;
228        }
229    
230        /**
231         * @see ArgsManager#getXidvZidvFileFilter()
232         */
233        @Override public PatternFileFilter getXidvZidvFileFilter() {
234            return Constants.FILTER_MCVMCVZ;
235        }
236    
237        /*
238         * There's some internal IDV file opening code that relies on this method.
239         * We've gotta override if we want to use .zidv bundles.
240         */
241        @Override public boolean isZidvFile(final String name) {
242            return isZippedBundle(name);
243        }
244    
245        /* same story as isZidvFile! */
246        @Override public boolean isXidvFile(final String name) {
247            return isXmlBundle(name);
248        }
249    
250        /**
251         * Tests to see if <code>name</code> has a known XML bundle extension.
252         * 
253         * @param name Name of the bundle.
254         * 
255         * @return Whether or not <code>name</code> has an XML bundle suffix.
256         */
257        public static boolean isXmlBundle(final String name) {
258            return IOUtil.hasSuffix(name, Constants.FILTER_MCV.getPreferredSuffix())
259                || IOUtil.hasSuffix(name, Constants.FILTER_XIDV.getPreferredSuffix());
260        }
261    
262        /**
263         * Tests to see if <code>name</code> has a known zipped bundle extension.
264         * 
265         * @param name Name of the bundle.
266         * 
267         * @return Whether or not <code>name</code> has zipped bundle suffix.
268         */
269        public static boolean isZippedBundle(final String name) {
270            return IOUtil.hasSuffix(name, Constants.FILTER_MCVZ.getPreferredSuffix())
271                   || IOUtil.hasSuffix(name, Constants.FILTER_ZIDV.getPreferredSuffix());
272        }
273    
274        /**
275         * Tests <code>name</code> to see if it has a known bundle extension.
276         * 
277         * @param name Name of the bundle.
278         * 
279         * @return Whether or not <code>name</code> has a bundle suffix.
280         */
281        public static boolean isBundle(final String name) {
282            return (isXmlBundle(name) || isZippedBundle(name));
283        }
284    }