001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.servicemix.common;
018    
019    import java.util.ArrayList;
020    import java.util.Collection;
021    import java.util.LinkedHashMap;
022    import java.util.List;
023    import java.util.Map;
024    
025    import javax.jbi.JBIException;
026    import javax.jbi.management.DeploymentException;
027    import javax.jbi.management.LifeCycleMBean;
028    
029    public class DefaultServiceUnit implements ServiceUnit {
030    
031        protected ServiceMixComponent component;
032    
033        protected String name;
034    
035        protected String rootPath;
036    
037        protected String status = LifeCycleMBean.SHUTDOWN;
038    
039        protected Map<String, Endpoint> endpoints = new LinkedHashMap<String, Endpoint>();
040    
041        public DefaultServiceUnit() {
042        }
043    
044        public DefaultServiceUnit(ServiceMixComponent component) {
045            this.component = component;
046        }
047    
048        public synchronized void init() throws Exception {
049            if (this.status == LifeCycleMBean.SHUTDOWN) {
050                // Activate endpoints
051                List<Endpoint> activated = new ArrayList<Endpoint>();
052                try {
053                    for (Endpoint endpoint : getEndpoints()) {
054                        endpoint.activate();
055                        activated.add(endpoint);
056                    }
057                    this.status = LifeCycleMBean.STOPPED;
058                } catch (Exception e) {
059                    // Deactivate activated endpoints
060                    for (Endpoint endpoint : activated) {
061                        try {
062                            endpoint.deactivate();
063                        } catch (Exception e2) {
064                            // do nothing
065                        }
066                    }
067                    throw e;
068                }
069            }
070        }
071    
072        public synchronized void start() throws Exception {
073            if (this.status == LifeCycleMBean.STOPPED) {
074                // Activate endpoints
075                List<Endpoint> activated = new ArrayList<Endpoint>();
076                try {
077                    for (Endpoint endpoint : getEndpoints()) {
078                        endpoint.start();
079                    }
080                    this.status = LifeCycleMBean.STARTED;
081                } catch (Exception e) {
082                    // Deactivate activated endpoints
083                    for (Endpoint endpoint : activated) {
084                        try {
085                            endpoint.stop();
086                        } catch (Exception e2) {
087                            // do nothing
088                        }
089                    }
090                    throw e;
091                }
092            }
093        }
094    
095        public synchronized void stop() throws Exception {
096            if (this.status == LifeCycleMBean.STARTED) {
097                this.status = LifeCycleMBean.STOPPED;
098                // Stop endpoints
099                Exception exception = null;
100                for (Endpoint endpoint : getEndpoints()) {
101                    try {
102                        endpoint.stop();
103                    } catch (Exception e) {
104                        exception = e;
105                    }
106                }
107                if (exception != null) {
108                    throw exception;
109                }
110            }
111        }
112    
113        public synchronized void shutDown() throws Exception {
114            if (this.status == LifeCycleMBean.STARTED) {
115                stop();
116            }
117            if (this.status == LifeCycleMBean.STOPPED) {
118                this.status = LifeCycleMBean.SHUTDOWN;
119                // Deactivate endpoints
120                Exception exception = null;
121                for (Endpoint endpoint : getEndpoints()) {
122                    try {
123                        // TODO: uncomment when all tests in various components work fine
124                        // TODO: we also need to find a way to not wait forever on this call
125                        //component.prepareShutdown(endpoint);
126                        endpoint.deactivate();
127                    } catch (Exception e) {
128                        exception = e;
129                    }
130                }
131                if (exception != null) {
132                    throw exception;
133                }
134            }
135        }
136    
137        public String getCurrentState() {
138            return status;
139        }
140    
141        public String getName() {
142            return name;
143        }
144    
145        public void setName(String name) {
146            this.name = name;
147        }
148    
149        public String getRootPath() {
150            return rootPath;
151        }
152    
153        public void setRootPath(String rootPath) {
154            this.rootPath = rootPath;
155        }
156    
157        /**
158         * @return Returns the component.
159         */
160        public ServiceMixComponent getComponent() {
161            return component;
162        }
163    
164        /**
165         * @param component
166         *            The component to set.
167         */
168        public void setComponent(ServiceMixComponent component) {
169            this.component = component;
170        }
171    
172        public Collection<Endpoint> getEndpoints() {
173            return this.endpoints.values();
174        }
175    
176        public synchronized void addEndpoint(Endpoint endpoint) throws DeploymentException {
177            String key = endpoint.getKey();
178            if (this.endpoints.put(key, endpoint) != null) {
179                throw new DeploymentException(
180                        "More than one endpoint found in the SU for key: " + key);
181            }
182            if (this.status == LifeCycleMBean.STOPPED) {
183                try {
184                    endpoint.activate();
185                } catch (Exception e) {
186                    throw new DeploymentException(e);
187                }
188            } else if (this.status == LifeCycleMBean.STARTED) {
189                try {
190                    endpoint.activate();
191                    endpoint.start();
192                } catch (Exception e) {
193                    throw new DeploymentException(e);
194                }
195            }
196        }
197    
198        public synchronized void removeEndpoint(Endpoint endpoint) throws DeploymentException {
199            String key = endpoint.getKey();
200            if (this.endpoints.remove(key) == null) {
201                throw new DeploymentException("Endpoint not found in the SU for key: " + EndpointSupport.getKey(endpoint));
202            }
203            if (this.status == LifeCycleMBean.STOPPED) {
204                try {
205                    component.prepareShutdown(endpoint);
206                    endpoint.deactivate();
207                } catch (Exception e) {
208                    throw new DeploymentException(e);
209                }
210            } else if (this.status == LifeCycleMBean.STARTED) {
211                try {
212                    endpoint.stop();
213                    component.prepareShutdown(endpoint);
214                    endpoint.deactivate();
215                } catch (Exception e) {
216                    throw new DeploymentException(e);
217                }
218            }
219        }
220    
221        public Endpoint getEndpoint(String key) {
222            return this.endpoints.get(key);
223        }
224    
225        public ClassLoader getConfigurationClassLoader() {
226            return component.getClass().getClassLoader();
227        }
228    
229    }