View Javadoc

1   /*
2    * ----------------------------------------------------------------------
3    * Copyright (C) 2009 Enrique Lara (k957@68k.org)
4    *
5    * TinLizard is free software; you can redistribute it and/or
6    * modify it under the terms of the GNU Lesser General Public License
7    * as published by the Free Software Foundation; either version 3.0
8    * of the License, or (at your option) any later version.
9    *
10   * TinLizard is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13   * GNU Lesser General Public License for more details.
14   *
15   * You should have received a copy of the GNU Lesser General Public License
16   * along with TinLizard. If not, see http://www.gnu.org/licenses/.
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); //XXX days ago as user input.
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); //Auto-create user if not exist.
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 }