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 */
017package org.apache.camel.impl;
018
019import java.util.ArrayList;
020import java.util.LinkedHashMap;
021import java.util.List;
022import java.util.Map;
023
024import org.apache.camel.CamelContext;
025import org.apache.camel.CamelContextAware;
026import org.apache.camel.Consumer;
027import org.apache.camel.Route;
028import org.apache.camel.Service;
029import org.apache.camel.ServiceStatus;
030import org.apache.camel.StatefulService;
031import org.apache.camel.StaticService;
032import org.apache.camel.spi.RestRegistry;
033import org.apache.camel.support.LifecycleStrategySupport;
034import org.apache.camel.support.ServiceSupport;
035import org.apache.camel.util.ObjectHelper;
036
037public class DefaultRestRegistry extends ServiceSupport implements StaticService, RestRegistry, CamelContextAware {
038
039    private CamelContext camelContext;
040    private final Map<Consumer, RestService> registry = new LinkedHashMap<Consumer, RestService>();
041
042    public void addRestService(Consumer consumer, String url, String baseUrl, String basePath, String uriTemplate, String method,
043                               String consumes, String produces, String inType, String outType, String routeId, String description) {
044        RestServiceEntry entry = new RestServiceEntry(consumer, url, baseUrl, basePath, uriTemplate, method, consumes, produces, inType, outType, routeId, description);
045        registry.put(consumer, entry);
046    }
047
048    public void removeRestService(Consumer consumer) {
049        registry.remove(consumer);
050    }
051
052    @Override
053    public List<RestRegistry.RestService> listAllRestServices() {
054        return new ArrayList<RestService>(registry.values());
055    }
056
057    @Override
058    public int size() {
059        return registry.size();
060    }
061
062    public CamelContext getCamelContext() {
063        return camelContext;
064    }
065
066    public void setCamelContext(CamelContext camelContext) {
067        this.camelContext = camelContext;
068    }
069
070    @Override
071    protected void doStart() throws Exception {
072        ObjectHelper.notNull(camelContext, "camelContext", this);
073        // add a lifecycle so we can keep track when consumers is being removed, so we can unregister them from our registry
074        camelContext.addLifecycleStrategy(new RemoveRestServiceLifecycleStrategy());
075    }
076
077    @Override
078    protected void doStop() throws Exception {
079        registry.clear();
080    }
081
082    /**
083     * Represents a rest service
084     */
085    private final class RestServiceEntry implements RestService {
086
087        private final Consumer consumer;
088        private final String url;
089        private final String baseUrl;
090        private final String basePath;
091        private final String uriTemplate;
092        private final String method;
093        private final String consumes;
094        private final String produces;
095        private final String inType;
096        private final String outType;
097        private final String routeId;
098        private final String description;
099
100        private RestServiceEntry(Consumer consumer, String url, String baseUrl, String basePath, String uriTemplate, String method,
101                                 String consumes, String produces, String inType, String outType, String routeId, String description) {
102            this.consumer = consumer;
103            this.url = url;
104            this.baseUrl = baseUrl;
105            this.basePath = basePath;
106            this.uriTemplate = uriTemplate;
107            this.method = method;
108            this.consumes = consumes;
109            this.produces = produces;
110            this.inType = inType;
111            this.outType = outType;
112            this.routeId = routeId;
113            this.description = description;
114        }
115
116        public Consumer getConsumer() {
117            return consumer;
118        }
119
120        public String getUrl() {
121            return url;
122        }
123
124        public String getBaseUrl() {
125            return baseUrl;
126        }
127
128        public String getBasePath() {
129            return basePath;
130        }
131
132        public String getUriTemplate() {
133            return uriTemplate;
134        }
135
136        public String getMethod() {
137            return method;
138        }
139
140        public String getConsumes() {
141            return consumes;
142        }
143
144        public String getProduces() {
145            return produces;
146        }
147
148        public String getInType() {
149            return inType;
150        }
151
152        public String getOutType() {
153            return outType;
154        }
155
156        public String getState() {
157            // must use String type to be sure remote JMX can read the attribute without requiring Camel classes.
158            ServiceStatus status = null;
159            if (consumer instanceof StatefulService) {
160                status = ((StatefulService) consumer).getStatus();
161            }
162            // if no status exists then its stopped
163            if (status == null) {
164                status = ServiceStatus.Stopped;
165            }
166            return status.name();
167        }
168
169        public String getRouteId() {
170            return routeId;
171        }
172
173        public String getDescription() {
174            return description;
175        }
176    }
177
178    /**
179     * A {@link org.apache.camel.spi.LifecycleStrategy} that keeps track when a {@link Consumer} is removed
180     * and automatic un-register it from this REST registry.
181     */
182    private final class RemoveRestServiceLifecycleStrategy extends LifecycleStrategySupport {
183
184        @Override
185        public void onServiceRemove(CamelContext context, Service service, Route route) {
186            super.onServiceRemove(context, service, route);
187
188            // if its a consumer then de-register it from the rest registry
189            if (service instanceof Consumer) {
190                removeRestService((Consumer) service);
191            }
192        }
193    }
194}