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