blob: daf16848be91e227b28148e304c23b5b962f3342 [file] [log] [blame]
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001package net.floodlightcontroller.restserver;
2
3import java.util.ArrayList;
4import java.util.Collection;
5import java.util.HashMap;
6import java.util.List;
7import java.util.Map;
8
Jonathan Hart285f2c22013-07-03 16:26:46 +12009import net.floodlightcontroller.core.module.FloodlightModuleContext;
10import net.floodlightcontroller.core.module.FloodlightModuleException;
11import net.floodlightcontroller.core.module.IFloodlightModule;
12import net.floodlightcontroller.core.module.IFloodlightService;
13
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080014import org.restlet.Application;
15import org.restlet.Component;
16import org.restlet.Context;
17import org.restlet.Request;
18import org.restlet.Response;
19import org.restlet.Restlet;
Jonathan Hart285f2c22013-07-03 16:26:46 +120020import org.restlet.Server;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080021import org.restlet.data.Protocol;
22import org.restlet.data.Reference;
23import org.restlet.data.Status;
24import org.restlet.ext.jackson.JacksonRepresentation;
25import org.restlet.representation.Representation;
26import org.restlet.routing.Filter;
27import org.restlet.routing.Router;
28import org.restlet.routing.Template;
29import org.restlet.service.StatusService;
30import org.slf4j.Logger;
31import org.slf4j.LoggerFactory;
32
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080033public class RestApiServer
34 implements IFloodlightModule, IRestApiService {
Yuta HIGUCHI6ac8d182013-10-22 15:24:56 -070035 protected final static Logger logger = LoggerFactory.getLogger(RestApiServer.class);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080036 protected List<RestletRoutable> restlets;
37 protected FloodlightModuleContext fmlContext;
38 protected int restPort = 8080;
Jonathan Hart285f2c22013-07-03 16:26:46 +120039 protected String numThreads = null;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080040
41 // ***********
42 // Application
43 // ***********
44
45 protected class RestApplication extends Application {
46 protected Context context;
47
48 public RestApplication() {
49 super(new Context());
50 this.context = getContext();
51 }
52
53 @Override
54 public Restlet createInboundRoot() {
55 Router baseRouter = new Router(context);
56 baseRouter.setDefaultMatchingMode(Template.MODE_STARTS_WITH);
57 for (RestletRoutable rr : restlets) {
58 baseRouter.attach(rr.basePath(), rr.getRestlet(context));
59 }
60
61 Filter slashFilter = new Filter() {
62 @Override
63 protected int beforeHandle(Request request, Response response) {
64 Reference ref = request.getResourceRef();
65 String originalPath = ref.getPath();
66 if (originalPath.contains("//"))
67 {
68 String newPath = originalPath.replaceAll("/+", "/");
69 ref.setPath(newPath);
70 }
71 return Filter.CONTINUE;
72 }
73
74 };
75 slashFilter.setNext(baseRouter);
76
77 return slashFilter;
78 }
79
80 public void run(FloodlightModuleContext fmlContext, int restPort) {
81 setStatusService(new StatusService() {
82 @Override
83 public Representation getRepresentation(Status status,
84 Request request,
85 Response response) {
86 return new JacksonRepresentation<Status>(status);
87 }
88 });
89
90 // Add everything in the module context to the rest
91 for (Class<? extends IFloodlightService> s : fmlContext.getAllServices()) {
92 if (logger.isTraceEnabled()) {
93 logger.trace("Adding {} for service {} into context",
94 s.getCanonicalName(), fmlContext.getServiceImpl(s));
95 }
96 context.getAttributes().put(s.getCanonicalName(),
97 fmlContext.getServiceImpl(s));
98 }
99
100 // Start listening for REST requests
101 try {
102 final Component component = new Component();
Jonathan Hart285f2c22013-07-03 16:26:46 +1200103 Server server = component.getServers().add(Protocol.HTTP, restPort);
104 if (numThreads != null){
105 logger.debug("Setting number of REST API threads to {}", numThreads);
106 server.getContext().getParameters().add("defaultThreads", numThreads);
107 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800108 component.getClients().add(Protocol.CLAP);
109 component.getDefaultHost().attach(this);
110 component.start();
111 } catch (Exception e) {
112 throw new RuntimeException(e);
113 }
114 }
115 }
116
117 // ***************
118 // IRestApiService
119 // ***************
120
121 @Override
122 public void addRestletRoutable(RestletRoutable routable) {
123 restlets.add(routable);
124 }
125
126 @Override
127 public void run() {
128 if (logger.isDebugEnabled()) {
129 StringBuffer sb = new StringBuffer();
130 sb.append("REST API routables: ");
131 for (RestletRoutable routable : restlets) {
132 sb.append(routable.getClass().getSimpleName());
133 sb.append(" (");
134 sb.append(routable.basePath());
135 sb.append("), ");
136 }
137 logger.debug(sb.toString());
138 }
139
140 RestApplication restApp = new RestApplication();
141 restApp.run(fmlContext, restPort);
142 }
143
144 // *****************
145 // IFloodlightModule
146 // *****************
147
148 @Override
149 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
150 Collection<Class<? extends IFloodlightService>> services =
151 new ArrayList<Class<? extends IFloodlightService>>(1);
152 services.add(IRestApiService.class);
153 return services;
154 }
155
156 @Override
157 public Map<Class<? extends IFloodlightService>, IFloodlightService>
158 getServiceImpls() {
159 Map<Class<? extends IFloodlightService>,
160 IFloodlightService> m =
161 new HashMap<Class<? extends IFloodlightService>,
162 IFloodlightService>();
163 m.put(IRestApiService.class, this);
164 return m;
165 }
166
167 @Override
168 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
169 // We don't have any
170 return null;
171 }
172
173 @Override
174 public void init(FloodlightModuleContext context)
175 throws FloodlightModuleException {
176 // This has to be done here since we don't know what order the
177 // startUp methods will be called
178 this.restlets = new ArrayList<RestletRoutable>();
179 this.fmlContext = context;
180
181 // read our config options
182 Map<String, String> configOptions = context.getConfigParams(this);
183 String port = configOptions.get("port");
184 if (port != null) {
185 restPort = Integer.parseInt(port);
186 }
187 logger.debug("REST port set to {}", restPort);
Jonathan Hart285f2c22013-07-03 16:26:46 +1200188
189 String numThreads = configOptions.get("dispatcherthreads");
190 if (numThreads != null) {
191 this.numThreads = numThreads;
192 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800193 }
194
195 @Override
196 public void startUp(FloodlightModuleContext Context) {
197 // no-op
198 }
199}