e5b95c812bd63545289d536d7a12894b6b217c95
[controller.git] / opendaylight / config / shutdown-impl / src / main / java / org / opendaylight / controller / config / yang / shutdown / impl / ShutdownServiceImpl.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.controller.config.yang.shutdown.impl;
9
10 import com.google.common.base.Optional;
11 import org.opendaylight.controller.config.shutdown.ShutdownService;
12 import org.osgi.framework.Bundle;
13 import org.osgi.framework.BundleException;
14 import org.slf4j.Logger;
15 import org.slf4j.LoggerFactory;
16
17 public class ShutdownServiceImpl implements ShutdownService, AutoCloseable {
18     private final ShutdownService impl;
19     private final ShutdownRuntimeRegistration registration;
20
21     public ShutdownServiceImpl(String secret, Bundle systemBundle,
22                                ShutdownRuntimeRegistrator rootRuntimeBeanRegistratorWrapper) {
23         if (secret == null) {
24             throw new IllegalArgumentException("Secret cannot be null");
25         }
26         impl = new Impl(secret, systemBundle);
27         registration = rootRuntimeBeanRegistratorWrapper.register(new MXBeanImpl(impl));
28     }
29
30     @Override
31     public void shutdown(String inputSecret, Optional<String> reason) {
32         impl.shutdown(inputSecret, reason);
33     }
34
35     @Override
36     public void close() {
37         registration.close();
38     }
39 }
40
41 class Impl implements ShutdownService {
42     private static final Logger logger = LoggerFactory.getLogger(Impl.class);
43     private final String secret;
44     private final Bundle systemBundle;
45
46     Impl(String secret, Bundle systemBundle) {
47         this.secret = secret;
48         this.systemBundle = systemBundle;
49     }
50
51     @Override
52     public void shutdown(String inputSecret, Optional<String> reason) {
53         logger.warn("Shutdown issued with secret {} and reason {}", inputSecret, reason);
54         try {
55             Thread.sleep(1000); // prevent brute force attack
56         } catch (InterruptedException e) {
57             Thread.currentThread().interrupt();
58             logger.warn("Shutdown process interrupted", e);
59         }
60         if (this.secret.equals(inputSecret)) {
61             logger.info("Server is shutting down");
62
63             Thread stopSystemBundle = new Thread() {
64                 @Override
65                 public void run() {
66                     try {
67                         // wait so that JMX response is received
68                         Thread.sleep(1000);
69                         systemBundle.stop();
70                     } catch (BundleException e) {
71                         logger.warn("Can not stop OSGi server", e);
72                     } catch (InterruptedException e) {
73                         logger.warn("Shutdown process interrupted", e);
74                     }
75                 }
76             };
77             stopSystemBundle.start();
78
79         } else {
80             logger.warn("Unauthorized attempt to shut down server");
81             throw new IllegalArgumentException("Invalid secret");
82         }
83     }
84
85 }
86
87 class MXBeanImpl implements ShutdownRuntimeMXBean {
88     private final ShutdownService impl;
89
90     MXBeanImpl(ShutdownService impl) {
91         this.impl = impl;
92     }
93
94     @Override
95     public void shutdown(String inputSecret, String nullableReason) {
96         Optional<String> optionalReason;
97         if (nullableReason == null) {
98             optionalReason = Optional.absent();
99         } else {
100             optionalReason = Optional.of(nullableReason);
101         }
102         impl.shutdown(inputSecret, optionalReason);
103     }
104 }