001    /*
002     * Created on May 23, 2008
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
005     * in compliance with the License. You may obtain a copy of the License at
006     *
007     * http://www.apache.org/licenses/LICENSE-2.0
008     *
009     * Unless required by applicable law or agreed to in writing, software distributed under the License
010     * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
011     * or implied. See the License for the specific language governing permissions and limitations under
012     * the License.
013     *
014     * Copyright @2008-2010 the original author or authors.
015     */
016    package org.fest.swing.launcher;
017    
018    import static org.fest.reflect.core.Reflection.staticMethod;
019    import static org.fest.swing.util.Arrays.copyOf;
020    import static org.fest.util.Strings.concat;
021    import static org.fest.util.Strings.quote;
022    
023    import org.fest.reflect.exception.ReflectionError;
024    import org.fest.swing.exception.UnexpectedException;
025    
026    /**
027     * Understands execution of a Java application from a class that has a "main" method.
028     * <p>
029     * The following example shows how to start an application without any arguments:
030     *
031     * <pre>
032     * ApplicationLauncher.application(JavaApp.class).start();
033     *
034     * // or
035     *
036     * ApplicationLauncher.{@link #application(String) application}(&quot;org.fest.swing.application.JavaApp&quot;).{@link #start() start}();
037     * </pre>
038     *
039     * </p>
040     * <p>
041     * The following example shows how to start an application with arguments:
042     *
043     * <pre>
044     * ApplicationLauncher.{@link #application(Class) application}(JavaApp.class).{@link #withArgs(String...) withArgs}(&quot;arg1&quot;, &quot;arg2&quot;).{@link #start() start}();
045     *
046     * // or
047     *
048     * ApplicationLauncher.{@link #application(String) application}(&quot;org.fest.swing.application.JavaApp&quot;).{@link #withArgs(String...) withArgs}(&quot;arg1&quot;, &quot;arg2&quot;).{@link #start() start}();
049     * </pre>
050     *
051     * </p>
052     *
053     * @author Yvonne Wang
054     */
055    public class ApplicationLauncher {
056    
057      /**
058       * Starting point of the fluent interface.
059       * @param applicationTypeName the fully qualified name of the class containing the "main" method.
060       * @return the created <code>ApplicationStarter</code>.
061       * @throws UnexpectedException if the class specified in the given name cannot be loaded.
062       */
063      public static ApplicationLauncher application(String applicationTypeName) {
064        try {
065          Class<?> applicationType = Thread.currentThread().getContextClassLoader().loadClass(applicationTypeName);
066          return application(applicationType);
067        } catch (ClassNotFoundException e) {
068          throw new UnexpectedException(concat("Unable to load class ", quote(applicationTypeName)), e);
069        }
070      }
071    
072      /**
073       * Starting point of the fluent interface.
074       * @param applicationType the class containing the "main" method.
075       * @return the created <code>ApplicationStarter</code>.
076       */
077      public static ApplicationLauncher application(Class<?> applicationType) {
078        return new ApplicationLauncher(applicationType);
079      }
080    
081      private final Class<?> applicationType;
082      private String[] args = new String[0];
083    
084      private ApplicationLauncher(Class<?> applicationType) {
085        this.applicationType = applicationType;
086      }
087    
088      /**
089       * Specifies the arguments to pass to the "main" method. Please note that the arguments to pass are specific to your
090       * application. JVM-specific arguments are ignored (e.g. -Xms, -Xmx)
091       * @param newArgs the arguments to pass to the "main" method.
092       * @return this <code>ApplicationStarter</code>.
093       * @throws NullPointerException if <code>newArgs</code> is <code>null</code>.
094       */
095      public ApplicationLauncher withArgs(String...newArgs) {
096        if (newArgs == null) throw new NullPointerException("The array of arguments should not be null");
097        args = copyOf(newArgs);
098        return this;
099      }
100    
101      /**
102       * Starts the application.
103       * @throws ReflectionError if the "main" method cannot be invoked.
104       */
105      public void start() {
106        staticMethod("main").withParameterTypes(String[].class).in(applicationType).invoke(new Object[] { args });
107      }
108    }