~ubuntu-branches/ubuntu/quantal/netbeans/quantal

« back to all changes in this revision

Viewing changes to core/bootstrap/src/org/netbeans/MainImpl.java

  • Committer: Bazaar Package Importer
  • Author(s): Marek Slama
  • Date: 2008-01-29 14:11:22 UTC
  • Revision ID: james.westby@ubuntu.com-20080129141122-fnzjbo11ntghxfu7
Tags: upstream-6.0.1
ImportĀ upstreamĀ versionĀ 6.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 
3
 *
 
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 
5
 *
 
6
 * The contents of this file are subject to the terms of either the GNU
 
7
 * General Public License Version 2 only ("GPL") or the Common
 
8
 * Development and Distribution License("CDDL") (collectively, the
 
9
 * "License"). You may not use this file except in compliance with the
 
10
 * License. You can obtain a copy of the License at
 
11
 * http://www.netbeans.org/cddl-gplv2.html
 
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
 
13
 * specific language governing permissions and limitations under the
 
14
 * License.  When distributing the software, include this License Header
 
15
 * Notice in each file and include the License file at
 
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
 
17
 * particular file as subject to the "Classpath" exception as provided
 
18
 * by Sun in the GPL Version 2 section of the License file that
 
19
 * accompanied this code. If applicable, add the following below the
 
20
 * License Header, with the fields enclosed by brackets [] replaced by
 
21
 * your own identifying information:
 
22
 * "Portions Copyrighted [year] [name of copyright owner]"
 
23
 *
 
24
 * Contributor(s):
 
25
 *
 
26
 * The Original Software is NetBeans. The Initial Developer of the Original
 
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
 
28
 * Microsystems, Inc. All Rights Reserved.
 
29
 *
 
30
 * If you wish your version of this file to be governed by only the CDDL
 
31
 * or only the GPL Version 2, indicate your decision by adding
 
32
 * "[Contributor] elects to include this software in this distribution
 
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
 
34
 * single choice of license, a recipient has the option to distribute
 
35
 * your version of this file under either the CDDL, the GPL Version 2 or
 
36
 * to extend the choice of license to its licensees as provided above.
 
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
 
38
 * Version 2 license, then the option applies only if the new code is
 
39
 * made subject to such option by the copyright holder.
 
40
 */
 
41
 
 
42
package org.netbeans;
 
43
 
 
44
import java.io.File;
 
45
import java.io.IOException;
 
46
import java.io.InputStream;
 
47
import java.lang.reflect.Method;
 
48
import java.net.URL;
 
49
import java.net.URLConnection;
 
50
import java.security.AllPermission;
 
51
import java.security.CodeSource;
 
52
import java.security.PermissionCollection;
 
53
import java.security.Permissions;
 
54
import java.util.ArrayList;
 
55
import java.util.Collection;
 
56
import java.util.Enumeration;
 
57
import java.util.HashSet;
 
58
import java.util.List;
 
59
import java.util.Set;
 
60
import java.util.StringTokenizer;
 
61
import org.openide.util.Lookup;
 
62
import org.openide.util.lookup.Lookups;
 
63
 
 
64
/** Bootstrap main class.
 
65
 * @author Jaroslav Tulach, Jesse Glick
 
66
 */
 
67
final class MainImpl extends Object {
 
68
 
 
69
    /** Starts the IDE.
 
70
     * @param args the command line arguments
 
71
     * @throws Exception for lots of reasons
 
72
     */
 
73
    public static void main (String args[]) throws Exception {
 
74
        java.lang.reflect.Method[] m = new java.lang.reflect.Method[1];
 
75
        int res = execute (args, System.in, System.out, System.err, m);
 
76
        if (res == -1) {
 
77
            // Connected to another running NB instance and succeeded in making a call.
 
78
            return;
 
79
        } else if (res != 0) {
 
80
            // Some CLIHandler refused the invocation
 
81
            System.exit(res);
 
82
        }
 
83
 
 
84
        m[0].invoke (null, new Object[] { args });
 
85
    }
 
86
 
 
87
    /** Returns string describing usage of the system. Does that by talking to
 
88
     * all registered handlers and asking them to show their usage.
 
89
     *
 
90
     * @return the usage string for the system
 
91
     */
 
92
    public static String usage () throws Exception {
 
93
        java.io.ByteArrayOutputStream os = new java.io.ByteArrayOutputStream ();
 
94
        java.io.ByteArrayOutputStream err = new java.io.ByteArrayOutputStream ();
 
95
 
 
96
        String[] newArgs = { "--help" };
 
97
 
 
98
        execute(newArgs, System.in, os, err, null);
 
99
        return new String (os.toByteArray ());
 
100
    }
 
101
 
 
102
    /** Constructs the correct ClassLoader, finds main method to execute
 
103
     * and invokes all registered CLIHandlers.
 
104
     *
 
105
     * @param args the arguments to pass to the handlers
 
106
     * @param reader the input stream reader for the handlers
 
107
     * @param writer the output stream for the handlers
 
108
     * @param methodToCall null or array with one item that will be set to
 
109
     *   a method that shall be executed as the main application
 
110
     */
 
111
    static int execute (
 
112
        String[] args,
 
113
        java.io.InputStream reader,
 
114
        java.io.OutputStream writer,
 
115
        java.io.OutputStream error,
 
116
        java.lang.reflect.Method[] methodToCall
 
117
    ) throws Exception {
 
118
        // #42431: turn off jar: caches, they are evil
 
119
        // Note that setDefaultUseCaches changes a static field
 
120
        // yet for some reason it is an instance method!
 
121
        new URLConnection(MainImpl.class.getResource("Main.class")) { // NOI18N
 
122
            public void connect() throws IOException {}
 
123
        }.setDefaultUseCaches(false);
 
124
 
 
125
        ArrayList<File> list = new ArrayList<File>();
 
126
 
 
127
        HashSet<File> processedDirs = new HashSet<File> ();
 
128
        String home = System.getProperty ("netbeans.home"); // NOI18N
 
129
        if (home != null) {
 
130
            build_cp (new File (home), list, processedDirs);
 
131
        }
 
132
        // #34069: need to do the same for nbdirs.
 
133
        String nbdirs = System.getProperty("netbeans.dirs"); // NOI18N
 
134
        if (nbdirs != null) {
 
135
            StringTokenizer tok = new StringTokenizer(nbdirs, File.pathSeparator);
 
136
            while (tok.hasMoreTokens()) {
 
137
                // passing false as last argument as we need to initialize openfile-cli.jar
 
138
                build_cp(new File(tok.nextToken()), list, processedDirs);
 
139
            }
 
140
        }
 
141
 
 
142
        //
 
143
        // prepend classpath
 
144
        //
 
145
        String prepend = System.getProperty("netbeans.classpath"); // NOI18N
 
146
        if (prepend != null) {
 
147
            StringTokenizer tok = new StringTokenizer (prepend, File.pathSeparator);
 
148
            while (tok.hasMoreElements()) {
 
149
                File f = new File(tok.nextToken());
 
150
                list.add(0, f);
 
151
            }
 
152
        }
 
153
 
 
154
        // Compute effective dynamic classpath (mostly lib/*.jar) for TopLogging, NbInstaller:
 
155
        StringBuffer buf = new StringBuffer(1000);
 
156
        for (File o : list) {
 
157
            String f = o.getAbsolutePath();
 
158
            if (buf.length() > 0) {
 
159
                buf.append(File.pathSeparatorChar);
 
160
            }
 
161
            buf.append(f);
 
162
        }
 
163
        System.setProperty("netbeans.dynamic.classpath", buf.toString());
 
164
 
 
165
        BootClassLoader loader = new BootClassLoader(list, new ClassLoader[] {
 
166
            MainImpl.class.getClassLoader()
 
167
        });
 
168
 
 
169
        // Needed for Lookup.getDefault to find NbTopManager.Lkp.
 
170
        // Note that ModuleManager.updateContextClassLoaders will later change
 
171
        // the loader on this and other threads to be MM.SystemClassLoader anyway.
 
172
        Thread.currentThread().setContextClassLoader (loader);
 
173
 
 
174
 
 
175
        //
 
176
        // Evaluate command line interfaces and lock the user directory
 
177
        //
 
178
 
 
179
        CLIHandler.Status result;
 
180
        result = CLIHandler.initialize(args, reader, writer, error, loader, true, false, loader);
 
181
        if (result.getExitCode () == CLIHandler.Status.CANNOT_CONNECT) {
 
182
            int value = javax.swing.JOptionPane.showConfirmDialog (
 
183
                null,
 
184
                java.util.ResourceBundle.getBundle("org/netbeans/Bundle").getString("MSG_AlreadyRunning"),
 
185
                java.util.ResourceBundle.getBundle("org/netbeans/Bundle").getString("MSG_AlreadyRunningTitle"),
 
186
                javax.swing.JOptionPane.OK_CANCEL_OPTION,
 
187
                javax.swing.JOptionPane.WARNING_MESSAGE
 
188
            );
 
189
            if (value == javax.swing.JOptionPane.OK_OPTION) {
 
190
                result = CLIHandler.initialize(args, reader, writer, error, loader, true, true, loader);
 
191
            }
 
192
 
 
193
        }
 
194
 
 
195
        String className = System.getProperty(
 
196
            "netbeans.mainclass", "org.netbeans.core.startup.Main" // NOI18N
 
197
        );
 
198
 
 
199
        Class<?> c = loader.loadClass(className);
 
200
        Method m = c.getMethod ("main", String[].class); // NOI18N
 
201
 
 
202
        if (methodToCall != null) {
 
203
            methodToCall[0] = m;
 
204
        }
 
205
 
 
206
        return result.getExitCode ();
 
207
    }
 
208
 
 
209
    /**
 
210
     * Call when the system is up and running, to complete handling of
 
211
     * delayed command-line options like -open FILE.
 
212
     */
 
213
    public static void finishInitialization() {
 
214
        int r = CLIHandler.finishInitialization (false);
 
215
        if (r != 0) {
 
216
            // Not much to do about it.
 
217
            System.err.println ("Post-initialization command-line options could not be run."); // NOI18N
 
218
            //System.err.println("r=" + r + " args=" + java.util.Arrays.asList(args.getArguments()));
 
219
        }
 
220
    }
 
221
 
 
222
    static final class BootClassLoader extends JarClassLoader
 
223
    implements Runnable {
 
224
        private Lookup metaInf;
 
225
 
 
226
        private List<CLIHandler> handlers;
 
227
 
 
228
        public BootClassLoader(List<File> cp, ClassLoader[] parents) {
 
229
            super(cp, parents);
 
230
 
 
231
            metaInf = Lookups.metaInfServices(this);
 
232
 
 
233
            String value = null;
 
234
            try {
 
235
                if (cp.isEmpty ()) {
 
236
                    value = searchBuildNumber(this.getResources("META-INF/MANIFEST.MF"));
 
237
                } else {
 
238
                    value = searchBuildNumber(this.simpleFindResources("META-INF/MANIFEST.MF"));
 
239
                }
 
240
            } catch (IOException ex) {
 
241
                ex.printStackTrace();
 
242
            }
 
243
 
 
244
            if (value == null) {
 
245
                System.err.println("Cannot set netbeans.buildnumber property no OpenIDE-Module-Implementation-Version found"); // NOI18N
 
246
            } else {
 
247
                System.setProperty ("netbeans.buildnumber", value); // NOI18N
 
248
            }
 
249
        }
 
250
 
 
251
        /** @param en enumeration of URLs */
 
252
        private static String searchBuildNumber(Enumeration<URL> en) {
 
253
            String value = null;
 
254
            try {
 
255
                java.util.jar.Manifest mf;
 
256
                URL u = null;
 
257
                while(en.hasMoreElements()) {
 
258
                    u = en.nextElement();
 
259
                    InputStream is = u.openStream();
 
260
                    mf = new java.util.jar.Manifest(is);
 
261
                    is.close();
 
262
                    value = mf.getMainAttributes().getValue("OpenIDE-Module-Implementation-Version"); // NOI18N
 
263
                    if (value != null) {
 
264
                        break;
 
265
                    }
 
266
                }
 
267
            } catch (IOException ex) {
 
268
                ex.printStackTrace();
 
269
            }
 
270
            return value;
 
271
        }
 
272
 
 
273
        private boolean onlyRunRunOnce;
 
274
        /** Checks for new JARs in netbeans.user */
 
275
        public void run () {
 
276
            // do not call this method twice
 
277
            if (onlyRunRunOnce) return;
 
278
            onlyRunRunOnce = true;
 
279
 
 
280
            ArrayList<File> toAdd = new ArrayList<File> ();
 
281
            String user = System.getProperty ("netbeans.user"); // NOI18N
 
282
            try {
 
283
                if (user != null) {
 
284
                    build_cp (new File (user), toAdd, new HashSet<File> ());
 
285
                }
 
286
 
 
287
                if (!toAdd.isEmpty ()) {
 
288
                    addSources (toAdd);
 
289
                    metaInf = Lookups.metaInfServices(this);
 
290
                    if (handlers != null) {
 
291
                        handlers.clear();
 
292
                        handlers.addAll(metaInf.lookupAll(CLIHandler.class));
 
293
                    }
 
294
                }
 
295
            } catch (IOException ex) {
 
296
                ex.printStackTrace();
 
297
            }
 
298
        }
 
299
 
 
300
 
 
301
        /** Startup optimalization. See issue 27226. */
 
302
        protected PermissionCollection getPermissions(CodeSource cs) {
 
303
            return getAllPermission();
 
304
        }
 
305
        /** Startup optimalization. See issue 27226. */
 
306
        private static PermissionCollection modulePermissions;
 
307
        /** Startup optimalization. See issue 27226. */
 
308
        private static synchronized PermissionCollection getAllPermission() {
 
309
            if (modulePermissions == null) {
 
310
                modulePermissions = new Permissions();
 
311
                modulePermissions.add(new AllPermission());
 
312
                modulePermissions.setReadOnly();
 
313
            }
 
314
            return modulePermissions;
 
315
        }
 
316
 
 
317
        /** For a given classloader finds all registered CLIHandlers.
 
318
         */
 
319
        public final Collection allCLIs () {
 
320
            if (handlers == null) {
 
321
                handlers = new ArrayList<CLIHandler>(metaInf.lookupAll(CLIHandler.class));
 
322
            }
 
323
            return handlers;
 
324
        }
 
325
    } // end of BootClassLoader
 
326
 
 
327
    private static void append_jars_to_cp (File dir, Collection<File> toAdd) throws IOException {
 
328
        if (!dir.isDirectory()) return;
 
329
 
 
330
        File[] arr = dir.listFiles();
 
331
        for (int i = 0; i < arr.length; i++) {
 
332
            String n = arr[i].getName ();
 
333
            /*
 
334
            if (n.equals("updater.jar") || // NOI18N
 
335
                (dir.getName().equals("locale") && n.startsWith("updater_") && n.endsWith(".jar"))) { // NOI18N
 
336
                // Used by launcher, not by us.
 
337
                continue;
 
338
            }
 
339
            */
 
340
            if (n.endsWith("jar") || n.endsWith ("zip")) { // NOI18N
 
341
                toAdd.add(arr[i]);
 
342
            }
 
343
        }
 
344
    }
 
345
 
 
346
 
 
347
    private static void build_cp(File base, Collection<File> toAdd, Set<File> processedDirs)
 
348
    throws java.io.IOException {
 
349
        if (!processedDirs.add (base)) {
 
350
            // already processed
 
351
            return;
 
352
        }
 
353
 
 
354
        append_jars_to_cp(new File(base, "core/patches"), toAdd); // NOI18N
 
355
        append_jars_to_cp(new File(base, "core"), toAdd); // NOI18N
 
356
        // XXX a minor optimization: exclude any unused locale JARs
 
357
        // For example, lib/locale/ might contain:
 
358
        // core_ja.jar
 
359
        // core_f4j.jar
 
360
        // core_f4j_ja.jar
 
361
        // core_f4j_ce.jar
 
362
        // core_f4j_ce_ja.jar
 
363
        // core_ru.jar
 
364
        // core_fr.jar
 
365
        // [etc.]
 
366
        // Only some of these will apply to the current session, based on the
 
367
        // current values of Locale.default and NbBundle.branding.
 
368
        append_jars_to_cp(new File(base, "core/locale"), toAdd); // NOI18N
 
369
    }
 
370
}