James Moger
2012-09-10 fabe060d3a435f116128851f828e35c2af5fde67
commit | author | age
db91a3 1 /*
JM 2  * Copyright 2011 gitblit.com.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.gitblit.utils;
17
797322 18 import java.io.FileNotFoundException;
JM 19 import java.io.IOException;
20 import java.lang.reflect.Type;
db91a3 21 import java.text.DateFormat;
797322 22 import java.text.MessageFormat;
db91a3 23 import java.text.SimpleDateFormat;
JM 24 import java.util.ArrayList;
25 import java.util.Calendar;
26 import java.util.Date;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Map;
40538c 30 import java.util.TimeZone;
db91a3 31
JM 32 import org.eclipse.jgit.lib.Constants;
33 import org.eclipse.jgit.lib.ObjectId;
34 import org.eclipse.jgit.lib.Repository;
35 import org.eclipse.jgit.revwalk.RevCommit;
36
37 import com.gitblit.GitBlit;
38 import com.gitblit.models.Activity;
39 import com.gitblit.models.Activity.RepositoryCommit;
797322 40 import com.gitblit.models.GravatarProfile;
db91a3 41 import com.gitblit.models.RefModel;
JM 42 import com.gitblit.models.RepositoryModel;
797322 43 import com.google.gson.reflect.TypeToken;
db91a3 44
JM 45 /**
46  * Utility class for building activity information from repositories.
47  * 
48  * @author James Moger
49  * 
50  */
51 public class ActivityUtils {
52
53     /**
54      * Gets the recent activity from the repositories for the last daysBack days
55      * on the specified branch.
56      * 
57      * @param models
58      *            the list of repositories to query
59      * @param daysBack
60      *            the number of days back from Now to collect
61      * @param objectId
9d921f 62      *            the branch to retrieve. If this value is null or empty all
JM 63      *            branches are queried.
40538c 64      * @param timezone
JM 65      *            the timezone for aggregating commits
db91a3 66      * @return
JM 67      */
68     public static List<Activity> getRecentActivity(List<RepositoryModel> models, int daysBack,
40538c 69             String objectId, TimeZone timezone) {
db91a3 70
JM 71         // Activity panel shows last daysBack of activity across all
72         // repositories.
73         Date thresholdDate = new Date(System.currentTimeMillis() - daysBack * TimeUtils.ONEDAY);
74
75         // Build a map of DailyActivity from the available repositories for the
76         // specified threshold date.
77         DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
40538c 78         df.setTimeZone(timezone);
db91a3 79         Calendar cal = Calendar.getInstance();
40538c 80         cal.setTimeZone(timezone);
db91a3 81
JM 82         Map<String, Activity> activity = new HashMap<String, Activity>();
83         for (RepositoryModel model : models) {
84             if (model.hasCommits && model.lastChange.after(thresholdDate)) {
9d921f 85                 Repository repository = GitBlit.self()
JM 86                         .getRepository(model.name);
87                 List<String> branches = new ArrayList<String>();
88                 if (StringUtils.isEmpty(objectId)) {
89                     for (RefModel local : JGitUtils.getLocalBranches(
90                             repository, true, -1)) {
91                         branches.add(local.getName());
92                     }
93                 } else {
94                     branches.add(objectId);
95                 }
96                 Map<ObjectId, List<RefModel>> allRefs = JGitUtils
97                         .getAllRefs(repository);
98
99                 for (String branch : branches) {
100                     String shortName = branch;
101                     if (shortName.startsWith(Constants.R_HEADS)) {
102                         shortName = shortName.substring(Constants.R_HEADS.length());
103                     }
104                     List<RevCommit> commits = JGitUtils.getRevLog(repository,
105                             branch, thresholdDate);
106                     for (RevCommit commit : commits) {
107                         Date date = JGitUtils.getCommitDate(commit);
108                         String dateStr = df.format(date);
109                         if (!activity.containsKey(dateStr)) {
110                             // Normalize the date to midnight
111                             cal.setTime(date);
112                             cal.set(Calendar.HOUR_OF_DAY, 0);
113                             cal.set(Calendar.MINUTE, 0);
114                             cal.set(Calendar.SECOND, 0);
115                             cal.set(Calendar.MILLISECOND, 0);
116                             activity.put(dateStr, new Activity(cal.getTime()));
117                         }
118                         RepositoryCommit commitModel = activity.get(dateStr)
119                                 .addCommit(model.name, shortName, commit);
120                         if (commitModel != null) {
121                             commitModel.setRefs(allRefs.get(commit.getId()));
122                         }
123                     }
124                 }
125                 
126                 // close the repository
db91a3 127                 repository.close();
JM 128             }
129         }
130
131         List<Activity> recentActivity = new ArrayList<Activity>(activity.values());
132         return recentActivity;
133     }
797322 134
JM 135     /**
136      * Returns the Gravatar profile, if available, for the specified email
137      * address.
138      * 
139      * @param emailaddress
140      * @return a Gravatar Profile
141      * @throws IOException
142      */
143     public static GravatarProfile getGravatarProfileFromAddress(String emailaddress)
144             throws IOException {
145         return getGravatarProfile(StringUtils.getMD5(emailaddress.toLowerCase()));
146     }
147
148     /**
149      * Creates a Gravatar thumbnail url from the specified email address.
150      * 
151      * @param email
152      *            address to query Gravatar
153      * @param width
62cec2 154      *            size of thumbnail. if width <= 0, the default of 50 is used.
797322 155      * @return
JM 156      */
157     public static String getGravatarThumbnailUrl(String email, int width) {
158         if (width <= 0) {
62cec2 159             width = 50;
797322 160         }
JM 161         String emailHash = StringUtils.getMD5(email);
162         String url = MessageFormat.format(
163                 "http://www.gravatar.com/avatar/{0}?s={1,number,0}&d=identicon", emailHash, width);
164         return url;
165     }
166
167     /**
168      * Returns the Gravatar profile, if available, for the specified hashcode.
169      * address.
170      * 
171      * @param hash
172      *            the hash of the email address
173      * @return a Gravatar Profile
174      * @throws IOException
175      */
176     public static GravatarProfile getGravatarProfile(String hash) throws IOException {
177         String url = MessageFormat.format("http://www.gravatar.com/{0}.json", hash);
178         // Gravatar has a complex json structure
179         Type profileType = new TypeToken<Map<String, List<GravatarProfile>>>() {
180         }.getType();
181         Map<String, List<GravatarProfile>> profiles = null;
182         try {
183             profiles = JsonUtils.retrieveJson(url, profileType);
184         } catch (FileNotFoundException e) {
185         }
186         if (profiles == null || profiles.size() == 0) {
187             return null;
188         }
189         // due to the complex json structure we need to pull out the profile
190         // from a list 2 levels deep
191         GravatarProfile profile = profiles.values().iterator().next().get(0);
192         return profile;
193     }
db91a3 194 }