Changes between Initial Version and Version 1 of waue/2009/0812d/Main_java


Ignore:
Timestamp:
Aug 12, 2009, 7:37:32 PM (15 years ago)
Author:
waue
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • waue/2009/0812d/Main_java

    v1 v1  
     1Main.java
     2
     3{{{
     4#!java
     5package start;
     6
     7import java.io.BufferedReader;
     8import java.io.File;
     9import java.io.FileInputStream;
     10import java.io.FilenameFilter;
     11import java.io.IOException;
     12import java.io.InputStream;
     13import java.io.InputStreamReader;
     14import java.lang.reflect.InvocationTargetException;
     15import java.lang.reflect.Method;
     16import java.security.Policy;
     17import java.util.ArrayList;
     18import java.util.Hashtable;
     19import java.util.StringTokenizer;
     20
     21/*-------------------------------------------*/
     22/**
     23 * Main start class. This class is intended to be the main class listed in the
     24 * MANIFEST.MF of the start.jar archive. It allows an application to be started
     25 * with the command "java -jar start.jar". The behaviour of Main is controlled
     26 * by the "org/mortbay/start/start.config" file obtained as a resource or file.
     27 * This can be overridden with the START system property. The format of each
     28 * line in this file is:
     29 *
     30 * <PRE>
     31 *
     32 * SUBJECT [ [!] CONDITION [AND|OR] ]*
     33 *
     34 * </PRE>
     35 *
     36 * where SUBJECT:
     37 *
     38 * <PRE>
     39 *
     40 * ends with &quot;.class&quot; is the Main class to run. ends with &quot;.xml&quot; is a configuration file for the
     41 * command line ends with &quot;/&quot; is a directory from which add all jar and zip files from. ends with
     42 * &quot;/*&quot; is a directory from which add all unconsidered jar and zip files from. Containing = are
     43 * used to assign system properties. all other subjects are treated as files to be added to the
     44 * classpath.
     45 *
     46 * </PRE>
     47 *
     48 * Subjects may include system properties with $(propertyname) syntax. File
     49 * subjects starting with "/" are considered absolute, all others are relative
     50 * to the home directory.
     51 * <P>
     52 * CONDITION is one of:
     53 *
     54 * <PRE>
     55 *
     56 * always never available package.class java OPERATOR n.n nargs OPERATOR n OPERATOR := one of &quot;
     57 * &lt;&quot;,&quot;&gt;&quot;,&quot; &lt;=&quot;,&quot;&gt;=&quot;,&quot;==&quot;,&quot;!=&quot;
     58 *
     59 * </PRE>
     60 *
     61 * CONTITIONS can be combined with AND OR or !, with AND being the assume
     62 * operator for a list of CONDITIONS. Classpath operations are evaluated on the
     63 * fly, so once a class or jar is added to the classpath, subsequent available
     64 * conditions will see that class. The system parameter CLASSPATH, if set is
     65 * given to the start classloader before any paths from the configuration file.
     66 * Programs started with start.jar may be stopped with the stop.jar, which
     67 * connects via a local port to stop the server. The default port can be set
     68 * with the STOP.PORT system property (a port of < 0 disables the stop
     69 * mechanism). If the STOP.KEY system property is set, then a random key is
     70 * generated and written to stdout. This key must be passed to the stop.jar.
     71 *
     72 * @author Jan Hlavaty (hlavac@code.cz)
     73 * @author Greg Wilkins
     74 * @version $Revision: 1.37 $
     75 */
     76@SuppressWarnings("unchecked")
     77public class Main {
     78
     79        static boolean _debug = System.getProperty("DEBUG", null) != null;
     80        private String _classname = null;
     81        private Classpath _classpath = new Classpath();
     82        private String _config = System.getProperty("START",
     83                        "start/start.config");
     84        private ArrayList<String> _xml = new ArrayList<String>();
     85
     86        public static void main(String[] args) {
     87                try {
     88                        new Main().start(args);
     89                } catch (Exception e) {
     90                        e.printStackTrace();
     91                }
     92        }
     93
     94        static File getDirectory(String name) {
     95                try {
     96                        if (name != null) {
     97                                File dir = new File(name).getCanonicalFile();
     98                                if (dir.isDirectory()) {
     99                                        return dir;
     100                                }
     101                        }
     102                } catch (IOException e) {
     103                }
     104                return null;
     105        }
     106
     107        boolean isAvailable(String classname) {
     108                try {
     109                        Class.forName(classname);
     110                        return true;
     111                } catch (NoClassDefFoundError e) {
     112                } catch (ClassNotFoundException e) {
     113                }
     114                ClassLoader loader = _classpath.getClassLoader();
     115                try {
     116                        loader.loadClass(classname);
     117                        return true;
     118                } catch (NoClassDefFoundError e) {
     119                } catch (ClassNotFoundException e) {
     120                }
     121                return false;
     122        }
     123
     124        public static void invokeMain(ClassLoader classloader, String classname,
     125                        String[] args) throws IllegalAccessException,
     126                        InvocationTargetException, NoSuchMethodException,
     127                        ClassNotFoundException {
     128                Class invoked_class = null;
     129                invoked_class = classloader.loadClass(classname);
     130                Class[] method_param_types = new Class[1];
     131                method_param_types[0] = args.getClass();
     132                Method main = null;
     133                main = invoked_class.getDeclaredMethod("main", method_param_types);
     134                Object[] method_params = new Object[1];
     135                method_params[0] = args;
     136                main.invoke(null, method_params);
     137        }
     138
     139        /* ------------------------------------------------------------ */
     140        String expand(String s) {
     141                int i1 = 0;
     142                int i2 = 0;
     143                while (s != null) {
     144                        i1 = s.indexOf("$(", i2);
     145                        if (i1 < 0)
     146                                break;
     147                        i2 = s.indexOf(")", i1 + 2);
     148                        if (i2 < 0)
     149                                break;
     150                        String property = System.getProperty(s.substring(i1 + 2, i2), "");
     151                        s = s.substring(0, i1) + property + s.substring(i2 + 1);
     152                }
     153                return s;
     154        }
     155
     156        /* ------------------------------------------------------------ */
     157
     158        void configure(InputStream config, int nargs) throws Exception {
     159                BufferedReader cfg = new BufferedReader(new InputStreamReader(config,
     160                                "ISO-8859-1"));
     161                Version java_version = new Version(System.getProperty("java.version"));
     162                Version ver = new Version();
     163                // JAR's already processed
     164                java.util.Hashtable done = new Hashtable();
     165                // Initial classpath
     166                String classpath = System.getProperty("CLASSPATH");
     167                if (classpath != null) {
     168                        StringTokenizer tok = new StringTokenizer(classpath,
     169                                        File.pathSeparator);
     170                        while (tok.hasMoreTokens())
     171                                _classpath.addComponent(tok.nextToken());
     172                }
     173                // Handle line by line
     174                String line = null;
     175                while (true) {
     176                        line = cfg.readLine();
     177                        if (line == null)
     178                                break;
     179                        if (line.length() == 0 || line.startsWith("#"))
     180                                continue;
     181                        try {
     182                                StringTokenizer st = new StringTokenizer(line);
     183                                String subject = st.nextToken();
     184                                subject = expand(subject);
     185                                boolean expression = true;
     186                                boolean not = false;
     187                                String condition = null;
     188                                // Evaluate all conditions
     189                                while (st.hasMoreTokens()) {
     190                                        condition = st.nextToken();
     191                                        if (condition.equalsIgnoreCase("!")) {
     192                                                not = true;
     193                                                continue;
     194                                        }
     195                                        if (condition.equalsIgnoreCase("OR")) {
     196                                                if (expression)
     197                                                        break;
     198                                                expression = true;
     199                                                continue;
     200                                        }
     201                                        if (condition.equalsIgnoreCase("AND")) {
     202                                                if (!expression)
     203                                                        break;
     204                                                continue;
     205                                        }
     206                                        boolean eval = true;
     207                                        if (condition.equals("true") || condition.equals("always")) {
     208                                                eval = true;
     209                                        } else if (condition.equals("false")
     210                                                        || condition.equals("never")) {
     211                                                eval = false;
     212                                        } else if (condition.equals("available")) {
     213                                                String class_to_check = st.nextToken();
     214                                                eval = isAvailable(class_to_check);
     215                                        } else if (condition.equals("exists")) {
     216                                                try {
     217                                                        eval = false;
     218                                                        File file = new File(expand(st.nextToken()));
     219                                                        eval = file.exists();
     220                                                } catch (Exception e) {
     221                                                        if (_debug)
     222                                                                e.printStackTrace();
     223                                                }
     224                                        } else if (condition.equals("property")) {
     225                                                String property = System.getProperty(st.nextToken());
     226                                                eval = property != null && property.length() > 0;
     227                                        } else if (condition.equals("java")) {
     228                                                String operator = st.nextToken();
     229                                                String version = st.nextToken();
     230                                                ver.parse(version);
     231                                                eval = (operator.equals("<") && java_version
     232                                                                .compare(ver) < 0)
     233                                                                || (operator.equals(">") && java_version
     234                                                                                .compare(ver) > 0)
     235                                                                || (operator.equals("<=") && java_version
     236                                                                                .compare(ver) <= 0)
     237                                                                || (operator.equals("=<") && java_version
     238                                                                                .compare(ver) <= 0)
     239                                                                || (operator.equals("=>") && java_version
     240                                                                                .compare(ver) >= 0)
     241                                                                || (operator.equals(">=") && java_version
     242                                                                                .compare(ver) >= 0)
     243                                                                || (operator.equals("==") && java_version
     244                                                                                .compare(ver) == 0)
     245                                                                || (operator.equals("!=") && java_version
     246                                                                                .compare(ver) != 0);
     247                                        } else if (condition.equals("nargs")) {
     248                                                String operator = st.nextToken();
     249                                                int number = Integer.parseInt(st.nextToken());
     250                                                eval = (operator.equals("<") && nargs < number)
     251                                                                || (operator.equals(">") && nargs > number)
     252                                                                || (operator.equals("<=") && nargs <= number)
     253                                                                || (operator.equals("=<") && nargs <= number)
     254                                                                || (operator.equals("=>") && nargs >= number)
     255                                                                || (operator.equals(">=") && nargs >= number)
     256                                                                || (operator.equals("==") && nargs == number)
     257                                                                || (operator.equals("!=") && nargs != number);
     258                                        } else {
     259                                                System.err.println("ERROR: Unknown condition: "
     260                                                                + condition);
     261                                                eval = false;
     262                                        }
     263                                        expression &= not ? !eval : eval;
     264                                        not = false;
     265                                }
     266
     267                                String file = subject.replace('/', File.separatorChar);
     268                                if (_debug)
     269                                        System.err.println((expression ? "T " : "F ") + line
     270                                                        + " subject=" + subject);
     271                                if (!expression) {
     272                                        done.put(file, file);
     273                                        continue;
     274                                }
     275                                // Handle the subject
     276                                if (subject.indexOf("=") > 0) {
     277                                        int i = file.indexOf("=");
     278                                        String property = file.substring(0, i);
     279                                        String value = file.substring(i + 1);
     280                                        if (_debug)
     281                                                System.err.println("  " + property + "=" + value);
     282                                        System.setProperty(property, value);
     283                                } else if (subject.endsWith("/*")) {
     284                                        // directory of JAR files
     285                                        File extdir = new File(file.substring(0, file.length() - 1));
     286                                        File[] jars = extdir.listFiles(new FilenameFilter() {
     287                                                public boolean accept(File dir, String name) {
     288                                                        String namelc = name.toLowerCase();
     289                                                        return namelc.endsWith(".jar")
     290                                                                        || name.endsWith(".zip");
     291                                                }
     292                                        });
     293                                        for (int i = 0; jars != null && i < jars.length; i++) {
     294                                                String jar = jars[i].getCanonicalPath();
     295                                                if (!done.containsKey(jar)) {
     296                                                        done.put(jar, jar);
     297                                                        boolean added = _classpath.addComponent(jar);
     298                                                        if (_debug)
     299                                                                System.err.println((added ? "  CLASSPATH+="
     300                                                                                : "  !")
     301                                                                                + jar);
     302                                                }
     303                                        }
     304                                } else if (subject.endsWith("/")) {
     305                                        // class directory
     306                                        File cd = new File(file);
     307                                        String d = cd.getCanonicalPath();
     308                                        if (!done.containsKey(d)) {
     309                                                done.put(d, d);
     310                                                boolean added = _classpath.addComponent(d);
     311                                                if (_debug)
     312                                                        System.err
     313                                                                        .println((added ? "  CLASSPATH+=" : "  !")
     314                                                                                        + d);
     315                                        }
     316                                } else if (subject.toLowerCase().endsWith(".xml")) {
     317                                        // Config file
     318                                        File f = new File(file);
     319                                        if (f.exists())
     320                                                _xml.add(f.getCanonicalPath());
     321                                        if (_debug)
     322                                                System.err.println("  ARGS+=" + f);
     323                                } else if (subject.toLowerCase().endsWith(".class")) {
     324                                        // Class
     325                                        String cn = expand(subject.substring(0,
     326                                                        subject.length() - 6));
     327                                        if (cn != null && cn.length() > 0) {
     328                                                if (_debug)
     329                                                        System.err.println("  CLASS=" + cn);
     330                                                _classname = cn;
     331                                        }
     332                                } else if (subject != null && subject.length() > 0) {
     333                                        // single JAR file
     334                                        File f = new File(file);
     335                                        String d = f.getCanonicalPath();
     336                                        if (!done.containsKey(d)) {
     337                                                done.put(d, d);
     338                                                boolean added = _classpath.addComponent(d);
     339                                                if (!added) {
     340                                                        added = _classpath.addClasspath(expand(subject));
     341                                                        if (_debug)
     342                                                                System.err.println((added ? "  CLASSPATH+="
     343                                                                                : "  !")
     344                                                                                + d);
     345                                                } else if (_debug)
     346                                                        System.err
     347                                                                        .println((added ? "  CLASSPATH+=" : "  !")
     348                                                                                        + d);
     349                                        }
     350                                }
     351                        } catch (Exception e) {
     352                                System.err.println("on line: '" + line + "'");
     353                                e.printStackTrace();
     354                        }
     355                }
     356        }
     357
     358        /* ------------------------------------------------------------ */
     359        public void start(String[] args) {
     360                ArrayList al = new ArrayList();
     361                for (int i = 0; i < args.length; i++) {
     362                        if (args[i] == null)
     363                                continue;
     364                        if (args[i].startsWith("-")) {
     365                                System.err
     366                                                .println("Usage: java [-DDEBUG] [-DSTART=start.config] [-Dmain.class=org.MyMain] -jar start.jar [--help] [config ...]");
     367                                System.exit(1);
     368                        } else
     369                                al.add(args[i]);
     370                }
     371                args = (String[]) al.toArray(new String[al.size()]);
     372                // set up classpath:
     373                InputStream cpcfg = null;
     374                try {
     375                        Monitor.monitor();
     376
     377                        cpcfg = getClass().getClassLoader().getResourceAsStream(_config);
     378                        if (_debug)
     379                                System.err.println("config=" + _config);
     380                        if (cpcfg == null)
     381                                cpcfg = new FileInputStream(_config);
     382                        configure(cpcfg, args.length);
     383                        File file = new File(System.getProperty("jetty.home"));
     384                        String canonical = file.getCanonicalPath();
     385                        System.setProperty("jetty.home", canonical);
     386                } catch (Exception e) {
     387                        e.printStackTrace();
     388                        System.exit(1);
     389                } finally {
     390                        try {
     391                                cpcfg.close();
     392                        } catch (Exception e) {
     393                                e.printStackTrace();
     394                        }
     395                }
     396                // okay, classpath complete.
     397                System.setProperty("java.class.path", _classpath.toString());
     398                ClassLoader cl = _classpath.getClassLoader();
     399                if (_debug) {
     400                        System.err.println("java.class.path="
     401                                        + System.getProperty("java.class.path"));
     402                        System.err
     403                                        .println("jetty.home=" + System.getProperty("jetty.home"));
     404                        System.err.println("java.io.tmpdir="
     405                                        + System.getProperty("java.io.tmpdir"));
     406                        System.err.println("java.class.path=" + _classpath);
     407                        System.err.println("classloader=" + cl);
     408                        System.err.println("classloader.parent=" + cl.getParent());
     409                }
     410                // Invoke main(args) using new classloader.
     411                Thread.currentThread().setContextClassLoader(cl);
     412                // re-eval the policy now that env is set
     413                try {
     414                        Policy policy = Policy.getPolicy();
     415                        if (policy != null)
     416                                policy.refresh();
     417                } catch (Exception e) {
     418                        e.printStackTrace();
     419                }
     420                try {
     421                        for (int i = 0; i < args.length; i++) {
     422                                if (args[i] == null)
     423                                        continue;
     424                                _xml.add(args[i]);
     425                        }
     426                        args = (String[]) _xml.toArray(args);
     427
     428                        if (_debug)
     429                                System.err.println("main.class=" + _classname);
     430                        invokeMain(cl, _classname, args);
     431                } catch (Exception e) {
     432                        e.printStackTrace();
     433                }
     434        }
     435}
     436}}}