Paul Martin
2016-04-27 17a6c6da2144a479169b90e055a1283d91a3e9ce
commit | author | age
bd0e83 1 /*
PM 2  * Copyright 2015 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.models;
17
18 import java.io.Serializable;
19 import java.util.ArrayList;
20 import java.util.Date;
21 import java.util.List;
22 import java.util.NoSuchElementException;
46f33f 23 import java.util.regex.Matcher;
PM 24 import java.util.regex.Pattern;
25
26 import com.gitblit.Constants;
bd0e83 27
PM 28 /**
29  * A FilestoreModel represents a file stored outside a repository but referenced by the repository using a unique objectID
30  * 
31  * @author Paul Martin
32  *
33  */
17a6c6 34 public class FilestoreModel implements Serializable, Comparable<FilestoreModel> {
bd0e83 35
PM 36     private static final long serialVersionUID = 1L;
37
46f33f 38     private static final String metaRegexText = new StringBuilder()
PM 39             .append("version\\shttps://git-lfs.github.com/spec/v1\\s+")
40             .append("oid\\ssha256:(" + Constants.REGEX_SHA256 + ")\\s+")
41             .append("size\\s([0-9]+)")
42             .toString();
43     
44     private static final Pattern metaRegex = Pattern.compile(metaRegexText);
45     
46     private static final int metaRegexIndexSHA = 1;
47     
48     private static final int metaRegexIndexSize = 2;
49     
bd0e83 50     public final String oid;
PM 51     
52     private Long size;
53     private Status status;
54     
55     //Audit
56     private String stateChangedBy;
57     private Date stateChangedOn;
58
59     //Access Control
60     private List<String> repositories;
61     
46f33f 62     public FilestoreModel(String id, long definedSize) {
PM 63         oid = id;
64         size = definedSize;
65         status = Status.ReferenceOnly;
66     }
67     
bd0e83 68     public FilestoreModel(String id, long expectedSize, UserModel user, String repo) {
PM 69         oid = id;
70         size = expectedSize;
71         status = Status.Upload_Pending;
72         stateChangedBy = user.getName();
73         stateChangedOn = new Date();
74         repositories = new ArrayList<String>();
75         repositories.add(repo);
46f33f 76     }
PM 77     
78     /*
79      * Attempts to create a FilestoreModel from the given meta string
80      * 
81      * @return A valid FilestoreModel if successful, otherwise null
82      */
83     public static FilestoreModel fromMetaString(String meta) {
84         
85         Matcher m = metaRegex.matcher(meta);
86         
87         if (m.find()) {
88             try
89             {
90                 final Long size = Long.parseLong(m.group(metaRegexIndexSize));
91                 final String sha = m.group(metaRegexIndexSHA);
92                 return new FilestoreModel(sha, size);            
93             } catch (Exception e) {
94                 //Fail silent - it is not a valid filestore item
95             }
96         }
97
98         return null;
bd0e83 99     }
PM 100     
101     public synchronized long getSize() {
102         return size;
103     }
104     
105     public synchronized Status getStatus() {
106         return status;
107     }
108     
109     public synchronized String getChangedBy() {
110         return stateChangedBy;
111     }
112     
113     public synchronized Date getChangedOn() {
114         return stateChangedOn;
115     }
116     
117     public synchronized void setStatus(Status status, UserModel user) {
118         this.status = status;
119         stateChangedBy = user.getName();
120         stateChangedOn = new Date();
121     }
122     
123     public synchronized void reset(UserModel user, long size) {
124         status = Status.Upload_Pending;
125         stateChangedBy = user.getName();
126         stateChangedOn = new Date();
127         this.size = size;
128     }
129     
130     /*
131      *  Handles possible race condition with concurrent connections
132      *  @return true if action can proceed, false otherwise
133      */
134     public synchronized boolean actionUpload(UserModel user) {
135         if (status == Status.Upload_Pending) {
136             status = Status.Upload_In_Progress;
137             stateChangedBy = user.getName();
138             stateChangedOn = new Date();
139             return true;
140         }
141         
142         return false;
143     }
144     
145     public synchronized boolean isInErrorState() {
146         return (this.status.value < 0);
147     }
148     
149     public synchronized void addRepository(String repo) {
46f33f 150         if (status != Status.ReferenceOnly) {
PM 151             if (!repositories.contains(repo)) {
152                 repositories.add(repo);
153             }
154         }
bd0e83 155     }
PM 156     
157     public synchronized void removeRepository(String repo) {
46f33f 158         if (status != Status.ReferenceOnly) {
PM 159             repositories.remove(repo);
160         }
bd0e83 161     }
PM 162     
697905 163     public synchronized boolean isInRepositoryList(List<String> repoList) {
46f33f 164         if (status != Status.ReferenceOnly) {
PM 165             for (String name : repositories) {
166                 if (repoList.contains(name)) {
167                     return true;
168                 }
697905 169             }
PM 170         }
171         return false;
172     }
173     
bd0e83 174     public static enum Status {
PM 175
46f33f 176         ReferenceOnly(-42),
PM 177         
bd0e83 178         Deleted(-30),
PM 179         AuthenticationRequired(-20),
180         
181         Error_Unknown(-8),
182         Error_Unexpected_Stream_End(-7),
183         Error_Invalid_Oid(-6),
184         Error_Invalid_Size(-5),
185         Error_Hash_Mismatch(-4),
186         Error_Size_Mismatch(-3), 
187         Error_Exceeds_Size_Limit(-2),
188         Error_Unauthorized(-1),
189         //Negative values provide additional information and may be treated as 0 when not required
190         Unavailable(0),
191         Upload_Pending(1),
192         Upload_In_Progress(2),
193         Available(3);
194
195         final int value;
196
197         Status(int value) {
198             this.value = value;
199         }
200
201         public int getValue() {
202             return value;
203         }
204
205         @Override
206         public String toString() {
207             return name().toLowerCase().replace('_', ' ');
208         }
209
210         public static Status fromState(int state) {
211             for (Status s : values()) {
212                 if (s.getValue() == state) {
213                     return s;
214                 }
215             }
216             throw new NoSuchElementException(String.valueOf(state));
217         }
218     }
219
17a6c6 220     @Override
PM 221     public int compareTo(FilestoreModel o) {
222         return this.oid.compareTo(o.oid);
223     }
224
bd0e83 225 }
PM 226