Source Code Cross Referenced for CLIHandler.java in  » IDE-Netbeans » library » org » netbeans » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Netbeans » library » org.netbeans 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003:         *
0004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * The contents of this file are subject to the terms of either the GNU
0007:         * General Public License Version 2 only ("GPL") or the Common
0008:         * Development and Distribution License("CDDL") (collectively, the
0009:         * "License"). You may not use this file except in compliance with the
0010:         * License. You can obtain a copy of the License at
0011:         * http://www.netbeans.org/cddl-gplv2.html
0012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013:         * specific language governing permissions and limitations under the
0014:         * License.  When distributing the software, include this License Header
0015:         * Notice in each file and include the License file at
0016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
0017:         * particular file as subject to the "Classpath" exception as provided
0018:         * by Sun in the GPL Version 2 section of the License file that
0019:         * accompanied this code. If applicable, add the following below the
0020:         * License Header, with the fields enclosed by brackets [] replaced by
0021:         * your own identifying information:
0022:         * "Portions Copyrighted [year] [name of copyright owner]"
0023:         *
0024:         * Contributor(s):
0025:         *
0026:         * The Original Software is NetBeans. The Initial Developer of the Original
0027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
0028:         * Microsystems, Inc. All Rights Reserved.
0029:         *
0030:         * If you wish your version of this file to be governed by only the CDDL
0031:         * or only the GPL Version 2, indicate your decision by adding
0032:         * "[Contributor] elects to include this software in this distribution
0033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034:         * single choice of license, a recipient has the option to distribute
0035:         * your version of this file under either the CDDL, the GPL Version 2 or
0036:         * to extend the choice of license to its licensees as provided above.
0037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
0038:         * Version 2 license, then the option applies only if the new code is
0039:         * made subject to such option by the copyright holder.
0040:         */
0041:
0042:        package org.netbeans;
0043:
0044:        import java.io.DataInputStream;
0045:        import java.io.DataOutputStream;
0046:        import java.io.EOFException;
0047:        import java.io.File;
0048:        import java.io.FileInputStream;
0049:        import java.io.FileOutputStream;
0050:        import java.io.IOException;
0051:        import java.io.InputStream;
0052:        import java.io.InterruptedIOException;
0053:        import java.io.OutputStream;
0054:        import java.io.PrintWriter;
0055:        import java.lang.reflect.InvocationTargetException;
0056:        import java.lang.reflect.Method;
0057:        import java.net.InetAddress;
0058:        import java.net.ServerSocket;
0059:        import java.net.Socket;
0060:        import java.net.SocketException;
0061:        import java.net.UnknownHostException;
0062:        import java.security.NoSuchAlgorithmException;
0063:        import java.security.SecureRandom;
0064:        import java.util.ArrayList;
0065:        import java.util.Arrays;
0066:        import java.util.Collection;
0067:        import java.util.Collections;
0068:        import java.util.Iterator;
0069:        import java.util.List;
0070:        import java.util.Random;
0071:        import java.util.logging.Level;
0072:        import java.util.logging.Logger;
0073:        import org.openide.util.RequestProcessor;
0074:        import org.openide.util.Task;
0075:
0076:        /**
0077:         * Command Line Interface and User Directory Locker support class.
0078:         * Subclasses may be registered into the system to handle special command-line options.
0079:         * To be registered, use <samp>META-INF/services/org.netbeans.CLIHandler</code>
0080:         * in a JAR file in the startup or dynamic class path (e.g. <samp>lib/ext/</samp>
0081:         * or <samp>lib/</samp>).
0082:         * @author Jaroslav Tulach
0083:         * @since org.netbeans.core/1 1.18
0084:         * @see "#32054"
0085:         * @see <a href="http://openide.netbeans.org/proposals/arch/cli.html">Specification</a>
0086:         */
0087:        public abstract class CLIHandler extends Object {
0088:            /** lenght of the key used for connecting */
0089:            private static final int KEY_LENGTH = 10;
0090:            /** ok reply */
0091:            private static final int REPLY_OK = 1;
0092:            /** sends exit code */
0093:            private static final int REPLY_EXIT = 2;
0094:            /** fail reply */
0095:            private static final int REPLY_FAIL = 0;
0096:            /** the server is active, but cannot compute the value now */
0097:            private static final int REPLY_DELAY = 3;
0098:
0099:            /** request to read from input stream */
0100:            private static final int REPLY_READ = 10;
0101:            /** request to write */
0102:            private static final int REPLY_WRITE = 11;
0103:            /** request to find out how much data is available */
0104:            private static final int REPLY_AVAILABLE = 12;
0105:            /** request to write to stderr */
0106:            private static final int REPLY_ERROR = 13;
0107:
0108:            /**
0109:             * Used during bootstrap sequence. Should only be used by core, not modules.
0110:             */
0111:            public static final int WHEN_BOOT = 1;
0112:            /**
0113:             * Used during later initialization or while NetBeans is up and running.
0114:             */
0115:            public static final int WHEN_INIT = 2;
0116:            /** Extra set of inits.
0117:             */
0118:            public static final int WHEN_EXTRA = 3;
0119:
0120:            /** reference to our server.
0121:             */
0122:            private static Server server;
0123:
0124:            /** Testing output of the threads.
0125:             */
0126:            private static Logger OUTPUT = Logger
0127:                    .getLogger("org.netbeans.CLIHandler"); // NOI18N
0128:
0129:            private int when;
0130:
0131:            /**
0132:             * Create a CLI handler and indicate its preferred timing.
0133:             * @param when when to run the handler: {@link #WHEN_BOOT} or {@link #WHEN_INIT}
0134:             */
0135:            protected CLIHandler(int when) {
0136:                this .when = when;
0137:            }
0138:
0139:            /**
0140:             * Process some set of command-line arguments.
0141:             * Unrecognized or null arguments should be ignored.
0142:             * Recognized arguments should be nulled out.
0143:             * @param args arguments
0144:             * @return error value or 0 if everything is all right
0145:             */
0146:            protected abstract int cli(Args args);
0147:
0148:            protected static void showHelp(PrintWriter w, Collection handlers,
0149:                    int when) {
0150:                Iterator it = handlers.iterator();
0151:                while (it.hasNext()) {
0152:                    CLIHandler h = (CLIHandler) it.next();
0153:                    if (when != -1 && when != h.when) {
0154:                        continue;
0155:                    }
0156:
0157:                    h.usage(w);
0158:                }
0159:            }
0160:
0161:            /**
0162:             * Print usage information for this handler.
0163:             * @param w a writer to print to
0164:             */
0165:            protected abstract void usage(PrintWriter w);
0166:
0167:            /** For testing purposes we can block the
0168:             * algorithm in any place in the initialize method.
0169:             */
0170:            private static void enterState(int state, Integer block) {
0171:                if (OUTPUT.isLoggable(Level.FINEST)) {
0172:                    synchronized (OUTPUT) {
0173:                        // for easier debugging of CLIHandlerTest
0174:                        OUTPUT.finest("state: " + state + " thread: "
0175:                                + Thread.currentThread()); // NOI18N
0176:                    }
0177:                }
0178:
0179:                if (block == null)
0180:                    return;
0181:
0182:                synchronized (block) {
0183:                    if (state == block.intValue()) {
0184:                        if (OUTPUT.isLoggable(Level.FINEST)) {
0185:                            OUTPUT.finest(state + " blocked"); // NOI18N
0186:                        }
0187:                        block.notifyAll();
0188:                        try {
0189:                            block.wait();
0190:                        } catch (InterruptedException ex) {
0191:                            throw new IllegalStateException();
0192:                        }
0193:                    } else {
0194:                        if (OUTPUT.isLoggable(Level.FINEST)) {
0195:                            OUTPUT.finest(state + " not blocked"); // NOI18N
0196:                        }
0197:                    }
0198:                }
0199:            }
0200:
0201:            private static boolean checkHelp(Args args, Collection handlers) {
0202:                String[] argv = args.getArguments();
0203:                for (int i = 0; i < argv.length; i++) {
0204:                    if (argv[i] == null) {
0205:                        continue;
0206:                    }
0207:
0208:                    if (argv[i].equals("-?") || argv[i].equals("--help")
0209:                            || argv[i].equals("-help")) { // NOI18N
0210:                        PrintWriter w = new PrintWriter(args.getOutputStream());
0211:                        showHelp(w, handlers, -1);
0212:                        w.flush();
0213:                        return true;
0214:                    }
0215:                }
0216:
0217:                return false;
0218:            }
0219:
0220:            /** Notification of available handlers.
0221:             * @return non-zero if one of the handlers fails
0222:             */
0223:            protected static int notifyHandlers(Args args, Collection handlers,
0224:                    int when, boolean failOnUnknownOptions, boolean consume) {
0225:                try {
0226:                    int r = 0;
0227:                    Iterator it = handlers.iterator();
0228:                    while (it.hasNext()) {
0229:                        CLIHandler h = (CLIHandler) it.next();
0230:                        if (h.when != when)
0231:                            continue;
0232:
0233:                        r = h.cli(args);
0234:                        //System.err.println("notifyHandlers: exit code " + r + " from " + h);
0235:                        if (r != 0) {
0236:                            return r;
0237:                        }
0238:                    }
0239:                    String[] argv = args.getArguments();
0240:                    if (failOnUnknownOptions) {
0241:                        argv = args.getArguments();
0242:                        for (int i = 0; i < argv.length; i++) {
0243:                            if (argv[i] != null) {
0244:                                // Unhandled option.
0245:                                PrintWriter w = new PrintWriter(args
0246:                                        .getOutputStream());
0247:                                w.println("Ignored unknown option: " + argv[i]); // NOI18N
0248:
0249:                                // XXX(-ttran) not good, this doesn't show the help for
0250:                                // switches handled by the launcher
0251:                                //
0252:                                //showHelp(w, handlers);
0253:
0254:                                w.flush();
0255:                                return 2;
0256:                            }
0257:                        }
0258:                    }
0259:                    return 0;
0260:                } finally {
0261:                    args.reset(consume);
0262:                }
0263:            }
0264:
0265:            /**
0266:             * Represents result of initialization.
0267:             * @see #initialize(String[], ClassLoader)
0268:             * @see #initialize(Args, Integer, List)
0269:             */
0270:            static final class Status {
0271:                public static final int CANNOT_CONNECT = -255;
0272:
0273:                private final File lockFile;
0274:                private final int port;
0275:                private int exitCode;
0276:                private Task parael;
0277:
0278:                /**
0279:                 * General failure.
0280:                 */
0281:                Status() {
0282:                    this (0);
0283:                }
0284:
0285:                /**
0286:                 * Failure due to a parse problem.
0287:                 * @param c bad status code (not 0)
0288:                 * @see #cli(Args)
0289:                 */
0290:                Status(int c) {
0291:                    this (null, 0, c, null);
0292:                }
0293:
0294:                /**
0295:                 * Some measure of success.
0296:                 * @param l the lock file (not null)
0297:                 * @param p the server port (not 0)
0298:                 * @param c a status code (0 or not)
0299:                 */
0300:                Status(File l, int p, int c, Task parael) {
0301:                    lockFile = l;
0302:                    port = p;
0303:                    exitCode = c;
0304:                    this .parael = parael;
0305:                }
0306:
0307:                private void waitFinished() {
0308:                    if (parael != null) {
0309:                        parael.waitFinished();
0310:                    }
0311:                }
0312:
0313:                /**
0314:                 * Get the lock file, if available.
0315:                 * @return the lock file, or null if there is none
0316:                 */
0317:                public File getLockFile() {
0318:                    waitFinished();
0319:                    return lockFile;
0320:                }
0321:
0322:                /**
0323:                 * Get the server port, if available.
0324:                 * @return a port number for the server, or 0 if there is no port open
0325:                 */
0326:                public int getServerPort() {
0327:                    return port;
0328:                }
0329:
0330:                /**
0331:                 * Get the CLI parse status.
0332:                 * @return 0 for success, some other value for error conditions
0333:                 */
0334:                public int getExitCode() {
0335:                    return exitCode;
0336:                }
0337:            }
0338:
0339:            /** Initializes the system by creating lock file.
0340:             *
0341:             * @param args the command line arguments to recognize
0342:             * @param classloader to find command CLIHandlers in
0343:             * @param failOnUnknownOptions if true, fail (status 2) if some options are not recognized (also checks for -? and -help)
0344:             * @param cleanLockFile removes lock file if it appears to be dead
0345:             * @return the file to be used as lock file or null parsing of args failed
0346:             */
0347:            static Status initialize(String[] args, InputStream is,
0348:                    OutputStream os, java.io.OutputStream err,
0349:                    MainImpl.BootClassLoader loader,
0350:                    boolean failOnUnknownOptions, boolean cleanLockFile,
0351:                    Runnable runWhenHome) {
0352:                return initialize(new Args(args, is, os, err, System
0353:                        .getProperty("user.dir")), (Integer) null, loader
0354:                        .allCLIs(), failOnUnknownOptions, cleanLockFile,
0355:                        runWhenHome);
0356:            }
0357:
0358:            /**
0359:             * What to do later when {@link #finishInitialization} is called.
0360:             * May remain null, otherwise contains list of Execute
0361:             */
0362:            private static List<Execute> doLater = new ArrayList<Execute>();
0363:
0364:            static interface Execute {
0365:                /** @return returns exit code */
0366:                public int exec();
0367:            }
0368:
0369:            /** Execute this runnable when finishInitialization method is called.
0370:             */
0371:            private static int registerFinishInstallation(Execute run) {
0372:                boolean runNow;
0373:
0374:                synchronized (CLIHandler.class) {
0375:                    if (doLater != null) {
0376:                        doLater.add(run);
0377:                        runNow = false;
0378:                    } else {
0379:                        runNow = true;
0380:                    }
0381:                }
0382:
0383:                if (runNow) {
0384:                    return run.exec();
0385:                }
0386:
0387:                return 0;
0388:            }
0389:
0390:            /**
0391:             * Run any {@link #WHEN_INIT} handlers that were passed to the original command line.
0392:             * Should be called when the system is up and ready.
0393:             * Cancels any existing actions, in case it is called twice.
0394:             * @return the result of executing the handlers
0395:             */
0396:            static int finishInitialization(boolean recreate) {
0397:                OUTPUT.log(Level.FINER, "finishInitialization {0}", recreate);
0398:                List toRun;
0399:                synchronized (CLIHandler.class) {
0400:                    toRun = doLater;
0401:                    doLater = recreate ? new ArrayList<Execute>() : null;
0402:                    if (OUTPUT.isLoggable(Level.FINER)) {
0403:                        OUTPUT.finer("Notify: " + toRun);
0404:                    }
0405:                    if (!recreate) {
0406:                        CLIHandler.class.notifyAll();
0407:                    }
0408:                }
0409:
0410:                if (toRun != null) {
0411:                    Iterator it = toRun.iterator();
0412:                    while (it.hasNext()) {
0413:                        Execute r = (Execute) it.next();
0414:                        int result = r.exec();
0415:                        if (result != 0) {
0416:                            return result;
0417:                        }
0418:                    }
0419:                }
0420:                return 0;
0421:            }
0422:
0423:            /** Blocks for a while and waits if the finishInitialization method
0424:             * was called.
0425:             * @param timeout ms to wait
0426:             * @return true if finishInitialization is over
0427:             */
0428:            private static synchronized boolean waitFinishInstallationIsOver(
0429:                    int timeout) {
0430:                if (doLater != null) {
0431:                    try {
0432:                        CLIHandler.class.wait(timeout);
0433:                    } catch (InterruptedException ex) {
0434:                        // go on, never mind
0435:                    }
0436:                }
0437:                return doLater == null;
0438:            }
0439:
0440:            /** Stops the server.
0441:             */
0442:            public static synchronized void stopServer() {
0443:                Server s = server;
0444:                if (s != null) {
0445:                    s.stopServer();
0446:                }
0447:            }
0448:
0449:            /** Enhanced search for localhost address that works also behind VPN
0450:             */
0451:            private static InetAddress localHostAddress() throws IOException {
0452:                java.net.NetworkInterface net = java.net.NetworkInterface
0453:                        .getByName("lo");
0454:                if (net == null || !net.getInetAddresses().hasMoreElements()) {
0455:                    return InetAddress.getLocalHost();
0456:                } else {
0457:                    return net.getInetAddresses().nextElement();
0458:                }
0459:            }
0460:
0461:            /** Initializes the system by creating lock file.
0462:             *
0463:             * @param args the command line arguments to recognize
0464:             * @param block the state we want to block in
0465:             * @param handlers all handlers to use
0466:             * @param failOnUnknownOptions if true, fail (status 2) if some options are not recognized (also checks for -? and -help)
0467:             * @param cleanLockFile removes lock file if it appears to be dead
0468:             * @param runWhenHome runnable to be executed when netbeans.user property is set
0469:             * @return a status summary
0470:             */
0471:            static Status initialize(final Args args, final Integer block,
0472:                    final Collection handlers,
0473:                    final boolean failOnUnknownOptions, boolean cleanLockFile,
0474:                    Runnable runWhenHome) {
0475:                // initial parsing of args
0476:                {
0477:                    int r = notifyHandlers(args, handlers, WHEN_BOOT, false,
0478:                            failOnUnknownOptions);
0479:                    if (r != 0) {
0480:                        return new Status(r);
0481:                    }
0482:                }
0483:
0484:                // get the value
0485:                String home = System.getProperty("netbeans.user"); // NOI18N
0486:                if (home == null) {
0487:                    home = System.getProperty("user.home"); // NOI18N
0488:                    System.setProperty("netbeans.user", home); // NOI18N
0489:                }
0490:
0491:                if ("memory".equals(home)) { // NOI18N
0492:                    return new Status(0);
0493:                }
0494:
0495:                if (runWhenHome != null) {
0496:                    // notify that we have successfully identified the home property
0497:                    runWhenHome.run();
0498:                }
0499:
0500:                File lockFile = new File(home, "lock"); // NOI18N
0501:
0502:                for (int i = 0; i < 5; i++) {
0503:                    // try few times to succeed
0504:                    try {
0505:                        if (lockFile.exists()) {
0506:                            enterState(5, block);
0507:                            throw new IOException("EXISTS"); // NOI18N
0508:                        }
0509:
0510:                        if (i == 0 && checkHelp(args, handlers)) {
0511:                            return new Status(2);
0512:                        }
0513:
0514:                        lockFile.getParentFile().mkdirs();
0515:                        lockFile.createNewFile();
0516:                        lockFile.deleteOnExit();
0517:                        secureAccess(lockFile);
0518:
0519:                        enterState(10, block);
0520:
0521:                        final byte[] arr = new byte[KEY_LENGTH];
0522:                        new Random().nextBytes(arr);
0523:
0524:                        server = new Server(arr, block, handlers,
0525:                                failOnUnknownOptions);
0526:
0527:                        final DataOutputStream os = new DataOutputStream(
0528:                                new FileOutputStream(lockFile));
0529:                        int p = server.getLocalPort();
0530:                        os.writeInt(p);
0531:                        os.flush();
0532:
0533:                        enterState(20, block);
0534:
0535:                        Task parael = new RequestProcessor("Secure CLI Port")
0536:                                .post(new Runnable() { // NOI18N
0537:                                    public void run() {
0538:                                        SecureRandom random = null;
0539:                                        enterState(95, block);
0540:                                        try {
0541:                                            random = SecureRandom
0542:                                                    .getInstance("SHA1PRNG"); // NOI18N
0543:                                        } catch (NoSuchAlgorithmException e) {
0544:                                            // #36966: IBM JDK doesn't have it.
0545:                                            try {
0546:                                                random = SecureRandom
0547:                                                        .getInstance("IBMSecureRandom"); // NOI18N
0548:                                            } catch (NoSuchAlgorithmException e2) {
0549:                                                // OK, disable server...
0550:                                                server.stopServer();
0551:                                            }
0552:                                        }
0553:
0554:                                        enterState(96, block);
0555:
0556:                                        if (random != null) {
0557:                                            random.nextBytes(arr);
0558:                                        }
0559:
0560:                                        enterState(97, block);
0561:
0562:                                        try {
0563:                                            os.write(arr);
0564:                                            os.flush();
0565:
0566:                                            enterState(27, block);
0567:                                            // if this turns to be slow due to lookup of getLocalHost
0568:                                            // address, it can be done asynchronously as nobody needs
0569:                                            // the address in the stream if the server is listening
0570:                                            byte[] host = InetAddress
0571:                                                    .getLocalHost()
0572:                                                    .getAddress();
0573:                                            if (block != null
0574:                                                    && block.intValue() == 667) {
0575:                                                // this is here to emulate #64004
0576:                                                throw new UnknownHostException(
0577:                                                        "dhcppc0"); // NOI18N
0578:                                            }
0579:                                            for (int all = 0; all < host.length; all++) {
0580:                                                os.write(host[all]);
0581:                                            }
0582:                                        } catch (UnknownHostException unknownHost) {
0583:                                            if (!"dhcppc0".equals(unknownHost
0584:                                                    .getMessage())) { // NOI18N, see above
0585:                                                // if we just cannot get the address, we can go on
0586:                                                unknownHost.printStackTrace();
0587:                                            }
0588:                                        } catch (IOException ex) {
0589:                                            ex.printStackTrace();
0590:                                        }
0591:                                        try {
0592:                                            os.close();
0593:                                        } catch (IOException ex) {
0594:                                            // ignore
0595:                                        }
0596:                                    }
0597:                                });
0598:
0599:                        int execCode = registerFinishInstallation(new Execute() {
0600:                            public int exec() {
0601:                                return notifyHandlers(args, handlers,
0602:                                        WHEN_INIT, failOnUnknownOptions,
0603:                                        failOnUnknownOptions);
0604:                            }
0605:
0606:                            public String toString() {
0607:                                return handlers.toString();
0608:                            }
0609:                        });
0610:
0611:                        enterState(0, block);
0612:                        return new Status(lockFile, server.getLocalPort(),
0613:                                execCode, parael);
0614:                    } catch (IOException ex) {
0615:                        if (!"EXISTS".equals(ex.getMessage())) { // NOI18N
0616:                            ex.printStackTrace();
0617:                        }
0618:                        // already exists, try to read
0619:                        byte[] key = null;
0620:                        byte[] serverAddress = null;
0621:                        int port = -1;
0622:                        DataInputStream is = null;
0623:                        try {
0624:                            enterState(21, block);
0625:                            if (OUTPUT.isLoggable(Level.FINER)) {
0626:                                OUTPUT.log(Level.FINER,
0627:                                        "Reading lock file {0}", lockFile); // NOI18N
0628:                            }
0629:                            is = new DataInputStream(new FileInputStream(
0630:                                    lockFile));
0631:                            port = is.readInt();
0632:                            enterState(22, block);
0633:                            key = new byte[KEY_LENGTH];
0634:                            is.readFully(key);
0635:                            enterState(23, block);
0636:                            byte[] x = new byte[4];
0637:                            is.readFully(x);
0638:                            enterState(24, block);
0639:                            serverAddress = x;
0640:                        } catch (EOFException eof) {
0641:                            // not yet fully written down
0642:                            if (port != -1) {
0643:                                try {
0644:                                    enterState(94, block);
0645:                                    // just wait a while
0646:                                    Thread.sleep(2000);
0647:                                } catch (InterruptedException inter) {
0648:                                    inter.printStackTrace();
0649:                                }
0650:                                continue;
0651:                            }
0652:                        } catch (IOException ex2) {
0653:                            // ok, try to read it once more
0654:                            enterState(26, block);
0655:                        } finally {
0656:                            if (is != null) {
0657:                                try {
0658:                                    is.close();
0659:                                } catch (IOException ex3) {
0660:                                    // ignore here
0661:                                }
0662:                            }
0663:                            enterState(25, block);
0664:                        }
0665:
0666:                        if (key != null && port != -1) {
0667:                            try {
0668:                                // ok, try to connect
0669:                                enterState(28, block);
0670:                                Socket socket = new Socket(localHostAddress(),
0671:                                        port);
0672:                                // wait max of 1s for reply
0673:                                socket.setSoTimeout(5000);
0674:                                DataOutputStream os = new DataOutputStream(
0675:                                        socket.getOutputStream());
0676:                                os.write(key);
0677:                                os.flush();
0678:
0679:                                enterState(30, block);
0680:
0681:                                DataInputStream replyStream = new DataInputStream(
0682:                                        socket.getInputStream());
0683:                                byte[] outputArr = new byte[4096];
0684:
0685:                                COMMUNICATION: for (;;) {
0686:                                    enterState(32, block);
0687:                                    int reply = replyStream.read();
0688:                                    //System.err.println("reply=" + reply);
0689:                                    enterState(34, block);
0690:
0691:                                    switch (reply) {
0692:                                    case REPLY_FAIL:
0693:                                        enterState(36, block);
0694:                                        break COMMUNICATION;
0695:                                    case REPLY_OK:
0696:                                        enterState(38, block);
0697:                                        // write the arguments
0698:                                        String[] arr = args.getArguments();
0699:                                        os.writeInt(arr.length);
0700:                                        for (int a = 0; a < arr.length; a++) {
0701:                                            os.writeUTF(arr[a]);
0702:                                        }
0703:                                        os.writeUTF(args.getCurrentDirectory()
0704:                                                .toString());
0705:                                        os.flush();
0706:                                        break;
0707:                                    case REPLY_EXIT:
0708:                                        int exitCode = replyStream.readInt();
0709:                                        if (exitCode == 0) {
0710:                                            // to signal end of the world
0711:                                            exitCode = -1;
0712:                                        }
0713:
0714:                                        os.close();
0715:                                        replyStream.close();
0716:
0717:                                        enterState(0, block);
0718:                                        return new Status(lockFile, port,
0719:                                                exitCode, null);
0720:                                    case REPLY_READ: {
0721:                                        enterState(42, block);
0722:                                        int howMuch = replyStream.readInt();
0723:                                        if (howMuch > outputArr.length) {
0724:                                            outputArr = new byte[howMuch];
0725:                                        }
0726:                                        int really = args.getInputStream()
0727:                                                .read(outputArr, 0, howMuch);
0728:                                        os.write(really);
0729:                                        if (really > 0) {
0730:                                            os.write(outputArr, 0, really);
0731:                                        }
0732:                                        os.flush();
0733:                                        break;
0734:                                    }
0735:                                    case REPLY_WRITE: {
0736:                                        enterState(44, block);
0737:                                        int howMuch = replyStream.readInt();
0738:                                        if (howMuch > outputArr.length) {
0739:                                            outputArr = new byte[howMuch];
0740:                                        }
0741:                                        replyStream.read(outputArr, 0, howMuch);
0742:                                        args.getOutputStream().write(outputArr,
0743:                                                0, howMuch);
0744:                                        break;
0745:                                    }
0746:                                    case REPLY_ERROR: {
0747:                                        enterState(45, block);
0748:                                        int howMuch = replyStream.readInt();
0749:                                        if (howMuch > outputArr.length) {
0750:                                            outputArr = new byte[howMuch];
0751:                                        }
0752:                                        replyStream.read(outputArr, 0, howMuch);
0753:                                        args.getErrorStream().write(outputArr,
0754:                                                0, howMuch);
0755:                                        break;
0756:                                    }
0757:                                    case REPLY_AVAILABLE:
0758:                                        enterState(46, block);
0759:                                        os.writeInt(args.getInputStream()
0760:                                                .available());
0761:                                        os.flush();
0762:                                        break;
0763:                                    case REPLY_DELAY:
0764:                                        enterState(47, block);
0765:                                        // ok, try once more
0766:                                        break;
0767:                                    case -1:
0768:                                        enterState(48, block);
0769:                                        // EOF. Why does this happen?
0770:                                        break;
0771:                                    default:
0772:                                        enterState(49, block);
0773:                                        assert false : reply;
0774:                                    }
0775:                                }
0776:
0777:                                // connection ok, butlockFile secret key not recognized
0778:                                // delete the lock file
0779:                            } catch (java.net.SocketTimeoutException ex2) {
0780:                                // connection failed, the port is dead
0781:                                enterState(33, block);
0782:                            } catch (java.net.ConnectException ex2) {
0783:                                // connection failed, the port is dead
0784:                                enterState(33, block);
0785:                            } catch (IOException ex2) {
0786:                                // some strange exception
0787:                                ex2.printStackTrace();
0788:                                enterState(33, block);
0789:                            }
0790:
0791:                            boolean isSameHost = true;
0792:                            if (serverAddress != null) {
0793:                                try {
0794:                                    isSameHost = Arrays.equals(InetAddress
0795:                                            .getLocalHost().getAddress(),
0796:                                            serverAddress);
0797:                                } catch (UnknownHostException ex5) {
0798:                                    // ok, we will not try to connect
0799:                                    enterState(999, block);
0800:                                }
0801:                            }
0802:
0803:                            if (cleanLockFile || isSameHost) {
0804:                                // remove the file and try once more
0805:                                lockFile.delete();
0806:                            } else {
0807:                                return new Status(Status.CANNOT_CONNECT);
0808:                            }
0809:                        }
0810:                    }
0811:
0812:                    try {
0813:                        enterState(83, block);
0814:                        Thread.sleep((int) (Math.random() * 1000.00));
0815:                        enterState(85, block);
0816:                    } catch (InterruptedException ex) {
0817:                        // means nothing
0818:                    }
0819:                }
0820:
0821:                // failure
0822:                return new Status();
0823:            }
0824:
0825:            /** Make the file readable just to its owner.
0826:             */
0827:            private static void secureAccess(final File file)
0828:                    throws IOException {
0829:                // using 1.6 method if available to make the file readable just 
0830:                // to its owner
0831:                boolean success = false;
0832:
0833:                String vm = System.getProperty("java.version"); // NOI18N
0834:                if (vm != null && vm.startsWith("1.6")) { // NOI18N
0835:                    try {
0836:                        Method m = File.class.getMethod("setReadable",
0837:                                new Class[] { Boolean.TYPE, Boolean.TYPE }); // NOI18N
0838:                        Object s1 = m.invoke(file, new Object[] {
0839:                                Boolean.FALSE, Boolean.FALSE });
0840:                        Object s2 = m.invoke(file, new Object[] { Boolean.TRUE,
0841:                                Boolean.TRUE });
0842:                        success = Boolean.TRUE.equals(s1)
0843:                                && Boolean.TRUE.equals(s2);
0844:                    } catch (InvocationTargetException ex) {
0845:                        ex.printStackTrace();
0846:                    } catch (IllegalAccessException ex) {
0847:                        ex.printStackTrace();
0848:                    } catch (NoSuchMethodException ex) {
0849:                        ex.printStackTrace();
0850:                    }
0851:                }
0852:                if (success) {
0853:                    return;
0854:                }
0855:                try {
0856:                    // try to make it only user-readable (on Unix)
0857:                    // since people are likely to leave a+r on their userdir
0858:                    File chmod = new File("/bin/chmod"); // NOI18N
0859:                    if (!chmod.isFile()) {
0860:                        // Linux uses /bin, Solaris /usr/bin, others hopefully one of those
0861:                        chmod = new File("/usr/bin/chmod"); // NOI18N
0862:                    }
0863:                    if (chmod.isFile()) {
0864:                        int chmoded = Runtime.getRuntime().exec(
0865:                                new String[] { chmod.getAbsolutePath(),
0866:                                        "go-rwx", // NOI18N
0867:                                        file.getAbsolutePath() }).waitFor();
0868:                        if (chmoded != 0) {
0869:                            throw new IOException("could not run " + chmod
0870:                                    + " go-rwx " + file); // NOI18N
0871:                        }
0872:                    }
0873:                } catch (InterruptedException e) {
0874:                    throw (IOException) new IOException(e.toString())
0875:                            .initCause(e);
0876:                }
0877:            }
0878:
0879:            /** Class that represents available arguments to the CLI
0880:             * handlers.
0881:             */
0882:            public static final class Args extends Object {
0883:                private String[] args;
0884:                private final String[] argsBackup;
0885:                private InputStream is;
0886:                private OutputStream os;
0887:                private OutputStream err;
0888:                private File currentDir;
0889:                private boolean closed;
0890:
0891:                Args(String[] args, InputStream is, OutputStream os,
0892:                        java.io.OutputStream err, String currentDir) {
0893:                    argsBackup = args;
0894:                    reset(false);
0895:                    this .is = is;
0896:                    this .os = os;
0897:                    this .err = err;
0898:                    this .currentDir = new File(currentDir);
0899:                }
0900:
0901:                /**
0902:                 * Restore the arguments list to a clean state.
0903:                 * If not consuming arguments, it is just set to the original list.
0904:                 * If consuming arguments, any nulled-out arguments are removed from the list.
0905:                 */
0906:                void reset(boolean consume) {
0907:                    if (consume) {
0908:                        String[] a = args;
0909:                        if (a == null) {
0910:                            a = argsBackup;
0911:                        }
0912:                        List<String> l = new ArrayList<String>(Arrays.asList(a));
0913:                        l.removeAll(Collections.singleton(null));
0914:                        args = l.toArray(new String[l.size()]);
0915:                    } else {
0916:                        args = argsBackup.clone();
0917:                    }
0918:                }
0919:
0920:                /** Closes the connection.
0921:                 */
0922:                final void close() {
0923:                    closed = true;
0924:                }
0925:
0926:                /**
0927:                 * Get the command-line arguments.
0928:                 * You may not modify the returned array except to set some elements
0929:                 * to null as you recognize them.
0930:                 * @return array of string arguments, may contain nulls
0931:                 */
0932:                public String[] getArguments() {
0933:                    return args;
0934:                }
0935:
0936:                /**
0937:                 * Get an output stream to which data may be sent.
0938:                 * @return stream to write to
0939:                 */
0940:                public OutputStream getOutputStream() {
0941:                    return os;
0942:                }
0943:
0944:                /** Access to error stream.
0945:                 * @return the stream to write error messages to
0946:                 */
0947:                public OutputStream getErrorStream() {
0948:                    return err;
0949:                }
0950:
0951:                public File getCurrentDirectory() {
0952:                    return currentDir;
0953:                }
0954:
0955:                /**
0956:                 * Get an input stream that may supply additional data.
0957:                 * @return stream to read from
0958:                 */
0959:                public InputStream getInputStream() {
0960:                    return is;
0961:                }
0962:
0963:                /** Is open? True if the connection is still alive. Can be
0964:                 * used with long running computations to find out if the
0965:                 * consumer of the output has not been interupted.
0966:                 *
0967:                 * @return true if the connection is still alive
0968:                 */
0969:                public boolean isOpen() {
0970:                    return !closed;
0971:                }
0972:
0973:            } // end of Args
0974:
0975:            /** Server that creates local socket and communicates with it.
0976:             */
0977:            private static final class Server extends Thread {
0978:                private byte[] key;
0979:                private ServerSocket socket;
0980:                private Integer block;
0981:                private Collection handlers;
0982:                private Socket work;
0983:                private static volatile int counter;
0984:                private final boolean failOnUnknownOptions;
0985:
0986:                private static long lastReply;
0987:                /** by default wait 100ms before sending a REPLY_FAIL message */
0988:                private static long failDelay = 100;
0989:
0990:                public Server(byte[] key, Integer block, Collection handlers,
0991:                        boolean failOnUnknownOptions) throws IOException {
0992:                    super ("CLI Requests Server"); // NOI18N
0993:                    this .key = key;
0994:                    this .setDaemon(true);
0995:                    this .block = block;
0996:                    this .handlers = handlers;
0997:                    this .failOnUnknownOptions = failOnUnknownOptions;
0998:
0999:                    socket = new ServerSocket(0, 50, localHostAddress());
1000:                    start();
1001:                }
1002:
1003:                public Server(Socket request, byte[] key, Integer block,
1004:                        Collection handlers, boolean failOnUnknownOptions)
1005:                        throws IOException {
1006:                    super ("CLI Handler Thread Handler: " + ++counter); // NOI18N
1007:                    this .key = key;
1008:                    this .setDaemon(true);
1009:                    this .block = block;
1010:                    this .handlers = handlers;
1011:                    this .work = request;
1012:                    this .failOnUnknownOptions = failOnUnknownOptions;
1013:
1014:                    start();
1015:                }
1016:
1017:                public int getLocalPort() {
1018:                    return socket.getLocalPort();
1019:                }
1020:
1021:                public void run() {
1022:                    if (work != null) {
1023:                        // I am a worker not listener server
1024:                        try {
1025:                            handleConnect(work);
1026:                        } catch (IOException ex) {
1027:                            ex.printStackTrace();
1028:                        }
1029:                        return;
1030:                    }
1031:
1032:                    ServerSocket toClose = socket;
1033:                    if (toClose == null) {
1034:                        return;
1035:                    }
1036:
1037:                    while (socket != null) {
1038:                        try {
1039:                            enterState(65, block);
1040:                            Socket s = socket.accept();
1041:                            if (socket == null) {
1042:                                enterState(66, block);
1043:                                s.getOutputStream().write(REPLY_FAIL);
1044:                                enterState(67, block);
1045:                                s.close();
1046:                                continue;
1047:                            }
1048:
1049:                            // spans new request handler
1050:                            new Server(s, key, block, handlers,
1051:                                    failOnUnknownOptions);
1052:                        } catch (InterruptedIOException ex) {
1053:                            if (socket != null) {
1054:                                ex.printStackTrace();
1055:                            }
1056:                            // otherwise ignore, we've just been asked by the stopServer
1057:                            // to stop
1058:                        } catch (java.net.SocketException ex) {
1059:                            if (socket != null) {
1060:                                ex.printStackTrace();
1061:                            }
1062:                        } catch (IOException ex) {
1063:                            ex.printStackTrace();
1064:                        }
1065:                    }
1066:
1067:                    try {
1068:                        toClose.close();
1069:                    } catch (IOException ex) {
1070:                        ex.printStackTrace();
1071:                    }
1072:                }
1073:
1074:                final void stopServer() {
1075:                    socket = null;
1076:                    // interrupts the listening server
1077:                    interrupt();
1078:                }
1079:
1080:                private void handleConnect(Socket s) throws IOException {
1081:
1082:                    byte[] check = new byte[key.length];
1083:                    DataInputStream is = new DataInputStream(s.getInputStream());
1084:
1085:                    enterState(70, block);
1086:
1087:                    is.readFully(check);
1088:
1089:                    enterState(90, block);
1090:
1091:                    final DataOutputStream os = new DataOutputStream(s
1092:                            .getOutputStream());
1093:
1094:                    if (Arrays.equals(check, key)) {
1095:                        while (!waitFinishInstallationIsOver(2000)) {
1096:                            os.write(REPLY_DELAY);
1097:                            os.flush();
1098:                        }
1099:
1100:                        enterState(93, block);
1101:                        os.write(REPLY_OK);
1102:                        os.flush();
1103:
1104:                        // continue with arguments
1105:                        int numberOfArguments = is.readInt();
1106:                        String[] args = new String[numberOfArguments];
1107:                        for (int i = 0; i < args.length; i++) {
1108:                            args[i] = is.readUTF();
1109:                        }
1110:                        final String currentDir = is.readUTF();
1111:
1112:                        final Args arguments = new Args(args, new IS(is, os),
1113:                                new OS(os, REPLY_WRITE),
1114:                                new OS(os, REPLY_ERROR), currentDir);
1115:
1116:                        class ComputingAndNotifying extends Thread {
1117:                            public int res;
1118:                            public boolean finished;
1119:
1120:                            public ComputingAndNotifying() {
1121:                                super ("Computes values in handlers");
1122:                            }
1123:
1124:                            public void run() {
1125:                                try {
1126:                                    if (checkHelp(arguments, handlers)) {
1127:                                        res = 2;
1128:                                    } else {
1129:                                        res = notifyHandlers(arguments,
1130:                                                handlers, WHEN_INIT,
1131:                                                failOnUnknownOptions, false);
1132:                                    }
1133:
1134:                                    if (res == 0) {
1135:                                        enterState(98, block);
1136:                                    } else {
1137:                                        enterState(99, block);
1138:                                    }
1139:                                } finally {
1140:                                    synchronized (this ) {
1141:                                        finished = true;
1142:                                        notifyAll();
1143:                                    }
1144:                                }
1145:                            }
1146:
1147:                            public synchronized void waitForResultAndNotifyOthers() {
1148:                                // execute the handlers in another thread
1149:                                start();
1150:                                while (!finished) {
1151:                                    try {
1152:                                        wait(1000);
1153:                                        os.write(REPLY_DELAY);
1154:                                        os.flush();
1155:                                    } catch (SocketException ex) {
1156:                                        if (isClosedSocket(ex)) { // NOI18N
1157:                                            // mark the arguments killed
1158:                                            arguments.close();
1159:                                            // interrupt this thread
1160:                                            interrupt();
1161:                                        } else {
1162:                                            ex.printStackTrace();
1163:                                        }
1164:                                    } catch (InterruptedException ex) {
1165:                                        ex.printStackTrace();
1166:                                    } catch (IOException ex) {
1167:                                        ex.printStackTrace();
1168:                                    }
1169:                                }
1170:                            }
1171:                        }
1172:                        ComputingAndNotifying r = new ComputingAndNotifying();
1173:                        r.waitForResultAndNotifyOthers();
1174:                        try {
1175:                            os.write(REPLY_EXIT);
1176:                            os.writeInt(r.res);
1177:                        } catch (SocketException ex) {
1178:                            if (isClosedSocket(ex)) { // NOI18N
1179:                                // mark the arguments killed
1180:                                arguments.close();
1181:                                // interrupt r thread
1182:                                r.interrupt();
1183:                            } else {
1184:                                throw ex;
1185:                            }
1186:                        }
1187:                    } else {
1188:                        enterState(103, block);
1189:                        long toWait = lastReply + failDelay
1190:                                - System.currentTimeMillis();
1191:                        if (toWait > 0) {
1192:                            try {
1193:                                Thread.sleep(toWait);
1194:                            } catch (InterruptedException ex) {
1195:                                ex.printStackTrace();
1196:                            }
1197:                            failDelay *= 2;
1198:                        } else {
1199:                            failDelay = 100;
1200:                        }
1201:                        lastReply = System.currentTimeMillis();
1202:                        os.write(REPLY_FAIL);
1203:                    }
1204:
1205:                    enterState(120, block);
1206:
1207:                    os.close();
1208:                    is.close();
1209:                }
1210:
1211:                /** A method to find out on various systems whether an exception is
1212:                 * a signal of closed socket, especially if the peer is killed or exited.
1213:                 * @param ex the exception to investigate
1214:                 */
1215:                static final boolean isClosedSocket(SocketException ex) {
1216:                    if (ex.getMessage().equals("Broken pipe")) { // NOI18N
1217:                        return true;
1218:                    }
1219:                    if (ex.getMessage().startsWith("Connection reset by peer")) { // NOI18N
1220:                        return true;
1221:                    }
1222:
1223:                    return false;
1224:                }
1225:
1226:                private static final class IS extends InputStream {
1227:                    private DataInputStream is;
1228:                    private DataOutputStream os;
1229:
1230:                    public IS(DataInputStream is, DataOutputStream os) {
1231:                        this .is = is;
1232:                        this .os = os;
1233:                    }
1234:
1235:                    public int read() throws IOException {
1236:                        byte[] arr = new byte[1];
1237:                        if (read(arr) == 1) {
1238:                            return arr[0];
1239:                        } else {
1240:                            return -1;
1241:                        }
1242:                    }
1243:
1244:                    public void close() throws IOException {
1245:                        super .close();
1246:                    }
1247:
1248:                    public int available() throws IOException {
1249:                        // ask for data
1250:                        os.write(REPLY_AVAILABLE);
1251:                        os.flush();
1252:                        // read provided data
1253:                        return is.readInt();
1254:                    }
1255:
1256:                    public int read(byte[] b) throws IOException {
1257:                        return read(b, 0, b.length);
1258:                    }
1259:
1260:                    public int read(byte[] b, int off, int len)
1261:                            throws IOException {
1262:                        // ask for data
1263:                        os.write(REPLY_READ);
1264:                        os.writeInt(len);
1265:                        os.flush();
1266:                        // read provided data
1267:                        int really = is.read();
1268:                        if (really > 0) {
1269:                            return is.read(b, off, really);
1270:                        } else {
1271:                            return really;
1272:                        }
1273:                    }
1274:
1275:                } // end of IS
1276:
1277:                private static final class OS extends OutputStream {
1278:                    private DataOutputStream os;
1279:                    private int type;
1280:
1281:                    public OS(DataOutputStream os, int type) {
1282:                        this .os = os;
1283:                        this .type = type;
1284:                    }
1285:
1286:                    public void write(int b) throws IOException {
1287:                        byte[] arr = { (byte) b };
1288:                        write(arr);
1289:                    }
1290:
1291:                    public void write(byte[] b) throws IOException {
1292:                        write(b, 0, b.length);
1293:                    }
1294:
1295:                    public void close() throws IOException {
1296:                        super .close();
1297:                    }
1298:
1299:                    public void flush() throws IOException {
1300:                        os.flush();
1301:                    }
1302:
1303:                    public void write(byte[] b, int off, int len)
1304:                            throws IOException {
1305:                        os.write(type);
1306:                        os.writeInt(len);
1307:                        os.write(b, off, len);
1308:                    }
1309:
1310:                } // end of OS
1311:
1312:            } // end of Server
1313:
1314:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.