1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package tinlizard.web;
20
21 import tinlizard.annotation.security.RolesAllowed;
22
23 import tinlizard.dataload.DataLoader;
24
25 import tinlizard.model.Codeline;
26 import tinlizard.model.Dependency;
27 import tinlizard.model.Policy;
28 import tinlizard.model.Project;
29 import tinlizard.model.TinLizard;
30 import tinlizard.model.TinLizardConfig;
31 import tinlizard.model.User;
32 import tinlizard.model.View;
33
34 import tinlizard.util.JndiUtil;
35 import tinlizard.util.Messages;
36
37 import java.io.Writer;
38 import java.net.URL;
39 import java.util.Collection;
40 import java.util.Date;
41 import java.util.HashMap;
42 import java.util.Locale;
43 import java.util.Map;
44
45 import javax.servlet.RequestDispatcher;
46 import javax.servlet.http.HttpSession;
47
48 import org.apache.log4j.Logger;
49
50 import org.codehaus.plexus.ContainerConfiguration;
51 import org.codehaus.plexus.DefaultContainerConfiguration;
52 import org.codehaus.plexus.DefaultPlexusContainer;
53 import org.codehaus.plexus.PlexusContainer;
54 import org.codehaus.plexus.PlexusContainerException;
55 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
56 import org.codehaus.plexus.util.StringUtils;
57
58 import org.kohsuke.stapler.StaplerRequest;
59 import org.kohsuke.stapler.StaplerResponse;
60 import org.kohsuke.stapler.export.Exported;
61
62 /***
63 * Root Object for Stapler.
64 *
65 * Misc.
66 * XXX search admin - clear indexes, index some, index all?
67 * XXX security CRUD per object or object group (project+codelines, users, views).
68 * XXX Artifact - get consumers needs to check groupId as well.
69 * XXX bubble up 0001 error in meaningful way to UI.
70 * XXX obtain effective-pom dependencies.
71 * XXX advanced search.
72 *
73 * Model
74 * XXX codeline create/lastmodified confusing - for the record in TL or for the actual codeline? maybe "admins" can set both?
75 * XXX project.getCodelineCount(Policy p);
76 * XXX user.getName();
77 * XXX reconsider changelog/scm interface.
78 * TODO: codeline - a depends on b.
79 * TODO: codeline - merge target
80 * TODO: reporting/summary - codeline/merge plan based on codeline merge target and inter-dependencies.
81 * TODO: codeline search - "bachelors" - no one depends on it?
82 *
83 * Activities:
84 * TODO: activity log for all events: Activity: EntityType,ID,Action,Actor,TimeStamp,IP.
85 *
86 * UI:
87 * XXX: scm connection in codelines.tag
88 * TODO: edit items "in place", instead of having to go to configure screen.
89 * TODO: "logan's run" age of codelines/views on UI. max age? configurable?
90 * TODO: ICONS: http://tango.freedesktop.org/Tango_Desktop_Project
91 * TODO: List out mvn scm:checkout commands to get all projects in view.
92 * TODO: implement HttpDeletable for applicable classes.
93 *
94 * Eclipse Integration
95 * TODO: eclipse - plugin to get codeline policy? right-click -> Team -> getCodelinePolicy().
96 *
97 * Hudson Integration:
98 * TODO: include sample scripts to show updating TinLizard from Hudson/Redmine, etc.
99 */
100 public final class TinLizardWeb extends ObjectWeb<TinLizard> {
101 private static final String PLEXUS_CONFIG = "/META-INF/plexus/tinlizard.xml";
102 private static final TinLizardWeb INSTANCE = new TinLizardWeb();
103 private static final Logger LOG = Logger.getLogger(TinLizardWeb.class);
104 private PlexusContainer plexus;
105
106 private TinLizardWeb() {
107 }
108
109 protected TinLizard getSubject() {
110 return TinLizard.getInstance();
111 }
112
113 public String getName() {
114 return TinLizard.getInstance().getName();
115 }
116
117 public static TinLizardWeb getInstance() {
118 return INSTANCE;
119 }
120
121 @Exported
122 public Date getCreated() {
123 return TinLizard.getInstance().getCreated();
124 }
125
126 @Exported
127 public String getCreatedBy() {
128 return TinLizard.getInstance().getCreatedBy();
129 }
130
131 @Exported
132 public Date getLastModified() {
133 return TinLizard.getInstance().getLastModified();
134 }
135
136 @Exported
137 public String getLastModifiedBy() {
138 return TinLizard.getInstance().getLastModifiedBy();
139 }
140
141 @Exported
142 public String getVersion() {
143 return TinLizard.getInstance().getVersion();
144 }
145
146 public void startup(String home) {
147 try {
148 ContainerConfiguration c = new DefaultContainerConfiguration();
149 Map<Object, Object> context = new HashMap<Object, Object>();
150 context.putAll(JndiUtil.getContextMap());
151 context.put("TINLIZARD_HOME", home);
152 c.setContext(context);
153
154 URL configuration = getClass().getResource(PLEXUS_CONFIG);
155 c.setContainerConfigurationURL(configuration);
156
157 plexus = new DefaultPlexusContainer(c);
158
159 TinLizardConfig tlconfig = (TinLizardConfig) plexus.lookup(TinLizardConfig.ROLE);
160 TinLizard.initialize(tlconfig);
161
162 if (JndiUtil.getBoolean(JndiUtil.LOADTESTDATA)) {
163 LOG.debug("Loading Test Data.");
164 new DataLoader().run();
165 }
166 } catch (PlexusContainerException e) {
167 throw new IllegalStateException(Messages.error_0500(), e);
168 } catch (ComponentLookupException e) {
169 throw new IllegalStateException(Messages.error_0501(), e);
170 }
171 }
172
173 public void shutdown() {
174 plexus.dispose();
175 }
176
177 public ProjectCollectionWeb getAllProjects() {
178 Collection<Project> allProjects = Project.findAll();
179
180 if (allProjects != null) {
181 return new ProjectCollectionWeb(allProjects, Messages._AllProjects());
182 } else {
183 return null;
184 }
185 }
186
187 public ProjectWeb getProject(final String name) {
188 if (LOG.isDebugEnabled()) {
189 LOG.debug(name);
190 }
191
192 Project p = Project.findByName(name);
193
194 if (p != null) {
195 return new ProjectWeb(p);
196 } else {
197 return null;
198 }
199 }
200
201 public ViewWeb getDefaultView() {
202 return new ViewWeb(View.getDefaultView());
203 }
204
205 public ViewCollectionWeb getAllViews() {
206 Collection<View> allViews = View.findAll();
207
208 if (allViews != null) {
209 return new ViewCollectionWeb(allViews, Messages._AllViews());
210 } else {
211 return null;
212 }
213 }
214
215 public ViewWeb getView(final String name) {
216 View view = View.findByName(name);
217
218 if (view != null) {
219 return new ViewWeb(view);
220 } else {
221 return null;
222 }
223 }
224
225 public CodelineCollectionWeb getAllCodelines() {
226 Collection<Codeline> allCodelines = Codeline.findAll();
227
228 if (allCodelines != null) {
229 return new CodelineCollectionWeb(allCodelines, Messages._AllCodelines());
230 } else {
231 return null;
232 }
233 }
234
235 public CodelineCollectionWeb getActiveCodelines() {
236 Collection<Codeline> allCodelines = Codeline.findAllActive();
237
238 if (allCodelines != null) {
239 return new CodelineCollectionWeb(allCodelines, Messages._ActiveCodelines());
240 } else {
241 return null;
242 }
243 }
244
245 public CodelineCollectionWeb getRecentlyModified() {
246 Collection<Codeline> allCodelines = Codeline.findRecentlyModified(5);
247
248 if (allCodelines != null) {
249 return new CodelineCollectionWeb(allCodelines, Messages._RecentlyModifiedCodelines());
250 } else {
251 return null;
252 }
253 }
254
255 public UserCollectionWeb getAllUsers() {
256 Collection<User> allUsers = User.findAll();
257
258 if (allUsers != null) {
259 return new UserCollectionWeb(allUsers, Messages._AllUsers());
260 } else {
261 return null;
262 }
263 }
264
265 public UserWeb getUser(final String name) {
266 User user = User.getUserByName(name, false);
267
268 if (user != null) {
269 return new UserWeb(user);
270 } else {
271 return null;
272 }
273 }
274
275 @RolesAllowed(RoleNames.USER)
276 public void doPreferences(final StaplerRequest request, final StaplerResponse response) throws Exception {
277 String username = request.getUserPrincipal().getName();
278
279 User.getUserByName(username, true);
280
281 response.sendRedirect(request.getContextPath() + "/user/" + username + "/configure");
282 }
283
284 public void applyTemplate(final Object it, final String template, final Writer out, final Locale locale, final String username) {
285 getSubject().getMashDao().applyTemplate(it, template, out, Locale.getDefault(), username);
286 }
287
288 public PolicyWeb getDefaultPolicy() {
289 return new PolicyWeb(Policy.getDefaultPolicy());
290 }
291
292 public PolicyCollectionWeb getAllPolicies() {
293 Collection<Policy> allPolicies = Policy.findAll();
294
295 if (allPolicies != null) {
296 return new PolicyCollectionWeb(allPolicies, Messages._AllPolicies());
297 } else {
298 return null;
299 }
300 }
301
302 public PolicyWeb getPolicy(final String name) {
303 Policy policy = Policy.findByName(name);
304
305 if (policy != null) {
306 return new PolicyWeb(policy);
307 } else {
308 return null;
309 }
310 }
311
312 public DependencyWeb getDependency(final String groupId) {
313 if (StringUtils.isNotBlank(groupId)) {
314 Dependency dependency = new Dependency();
315 dependency.setGroupId(groupId);
316
317 return new GroupWeb(dependency);
318 }
319
320 return null;
321 }
322
323 @RolesAllowed(RoleNames.USER)
324 public void doAddProject(final StaplerRequest request, final StaplerResponse response) throws Exception {
325 Project p = new Project();
326 request.bindParameters(p, "project.");
327
328 Codeline c = new Codeline();
329 request.bindParameters(c, "codeline.");
330
331 User user = new User();
332 request.bindParameters(user, "owner.");
333 user = User.getUserByName(user.getName(), true);
334
335 boolean updateFromPom = Boolean.parseBoolean(request.getParameter("updateFromPom"));
336
337 Project project = Project.add(user, p, c, updateFromPom);
338 response.sendRedirect(request.getContextPath() + "/project/" + project.getName());
339 }
340
341 @RolesAllowed(RoleNames.USER)
342 public void doAddView(final StaplerRequest request, final StaplerResponse response) throws Exception {
343 View view = new View();
344 request.bindParameters(view, "view.");
345
346 view.add();
347 response.sendRedirect(request.getContextPath() + "/view/" + view.getName());
348 }
349
350 @RolesAllowed(RoleNames.ADMIN)
351 public void doAddPolicy(final StaplerRequest request, final StaplerResponse response) throws Exception {
352 Policy policy = new Policy();
353 request.bindParameters(policy, "policy.");
354
355 policy.add();
356 response.sendRedirect(request.getContextPath() + "/policy/" + policy.getName());
357 }
358
359 /***
360 * Let container managed security handle the rest.
361 */
362 public void doLogin(final StaplerRequest request, final StaplerResponse response) throws Exception {
363 response.sendRedirect(request.getContextPath());
364 }
365
366 public void doLogout(final StaplerRequest request, final StaplerResponse response) throws Exception {
367 if (LOG.isDebugEnabled() && (request.getUserPrincipal() != null)) {
368 LOG.debug((("doLogout:" + request.getUserPrincipal()) != null) ? request.getUserPrincipal().getName() : "");
369 }
370
371 HttpSession session = request.getSession(false);
372
373 if (session != null) {
374 session.invalidate();
375 }
376
377 response.sendRedirect(request.getContextPath());
378 }
379
380 public void doSearch(final StaplerRequest request, final StaplerResponse response) throws Exception {
381 String type = request.getParameter("type");
382 String query = request.getParameter("query");
383
384 final Object results;
385
386 if ("Dependency".equals(type)) {
387 Collection<Dependency> dependencies = Dependency.search(query);
388 results = new DependencyCollectionWeb(dependencies, Messages._SearchResults(query));
389 } else {
390 Collection<Codeline> codelines = Codeline.search(query);
391 results = new CodelineCollectionWeb(codelines, Messages._SearchResults(query));
392 }
393
394 request.setAttribute(javax.servlet.jsp.jstl.core.Config.FMT_FALLBACK_LOCALE, response.getLocale());
395
396 RequestDispatcher view = request.getView(results, "index.jsp");
397 view.include(request, response);
398 }
399
400 @RolesAllowed(RoleNames.USER)
401 public void doIndexAll(final StaplerRequest request, final StaplerResponse response) throws Exception {
402 getSubject().indexAll();
403
404 response.sendRedirect(request.getContextPath());
405 }
406 }