001    package org.apache.archiva.audit;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     *  http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import org.apache.archiva.metadata.model.MetadataFacet;
023    
024    import java.text.ParseException;
025    import java.text.SimpleDateFormat;
026    import java.util.Calendar;
027    import java.util.Date;
028    import java.util.HashMap;
029    import java.util.Map;
030    import java.util.TimeZone;
031    
032    /**
033     * AuditEvent
034     *
035     *
036     */
037    public class AuditEvent
038        implements MetadataFacet
039    {
040        public static final String TIMESTAMP_FORMAT = "yyyy/MM/dd/HHmmss.SSS";
041    
042        public static final String CREATE_DIR = "Created Directory";
043    
044        public static final String CREATE_FILE = "Created File";
045    
046        public static final String REMOVE_DIR = "Removed Directory";
047    
048        public static final String REMOVE_FILE = "Removed File";
049    
050        public static final String MODIFY_FILE = "Modified File";
051    
052        public static final String MOVE_FILE = "Moved File";
053    
054        public static final String MOVE_DIRECTORY = "Moved Directory";
055    
056        public static final String COPY_DIRECTORY = "Copied Directory";
057    
058        public static final String COPY_FILE = "Copied File";
059    
060        public static final String UPLOAD_FILE = "Uploaded File";
061    
062        public static final String ADD_LEGACY_PATH = "Added Legacy Artifact Path";
063    
064        public static final String REMOVE_LEGACY_PATH = "Removed Legacy Artifact Path";
065    
066        public static final String PURGE_ARTIFACT = "Purged Artifact";
067    
068        public static final String PURGE_FILE = "Purged Support File";
069    
070        public static final String REMOVE_SCANNED = "Removed in Filesystem";
071    
072        public static final String MERGING_REPOSITORIES = "Merged Artifact";
073    
074        // configuration events
075    
076        public static final String ADD_MANAGED_REPO = "Added Managed Repository";
077    
078        public static final String MODIFY_MANAGED_REPO = "Updated Managed Repository";
079    
080        public static final String DELETE_MANAGED_REPO = "Deleted Managed Repository";
081    
082        public static final String ADD_REMOTE_REPO = "Added Remote Repository";
083    
084        public static final String MODIFY_REMOTE_REPO = "Updated Remote Repository";
085    
086        public static final String DELETE_REMOTE_REPO = "Deleted Remote Repository";
087    
088        public static final String ADD_REPO_GROUP = "Added Repository Group";
089    
090        public static final String DELETE_REPO_GROUP = "Deleted Repository Group";
091    
092        public static final String MODIFY_REPO_GROUP = "Modify Repository Group";
093    
094        public static final String ADD_REPO_TO_GROUP = "Added Repository to Group";
095    
096        public static final String DELETE_REPO_FROM_GROUP = "Deleted Repository from Group";
097    
098        public static final String ENABLE_REPO_CONSUMER = "Enabled Content Consumer";
099    
100        public static final String DISABLE_REPO_CONSUMER = "Disabled Content Consumer";
101    
102        public static final String ADD_PATTERN = "Added File Type Pattern";
103    
104        public static final String REMOVE_PATTERN = "Removed File Type Pattern";
105    
106        public static final String MERGE_REPO_REMOTE = "Merged Staging Repository Triggered Remotely";
107    
108        public static final String ADD_PROXY_CONNECTOR = "Added Proxy Connector";
109    
110        public static final String DELETE_PROXY_CONNECTOR = "Deleted Proxy Connector";
111    
112        public static final String MODIFY_PROXY_CONNECTOR = "Updated Proxy Connector";
113    
114        public static final String ADD_NETWORK_PROXY = "Added Network Proxy";
115    
116        public static final String DELETE_NETWORK_PROXY = "Deleted Network Proxy";
117    
118        public static final String MODIFY_NETWORK_PROXY = "Updated Network Proxy";
119        
120        private String repositoryId;
121    
122        private String userId;
123    
124        private String remoteIP;
125    
126        // TODO: change to artifact reference? does it ever refer to just a path?
127    
128        private String resource;
129    
130        private String action;
131    
132        private Date timestamp;
133    
134        public static final String FACET_ID = "org.apache.archiva.audit";
135    
136        private static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone( "UTC" );
137    
138        private static final int TS_LENGTH = TIMESTAMP_FORMAT.length();
139    
140        public AuditEvent()
141        {
142            /* do nothing */
143        }
144    
145        public AuditEvent( String name, String repositoryId )
146        {
147            String ts = name.substring( 0, TS_LENGTH );
148            try
149            {
150                timestamp = createNameFormat().parse( ts );
151            }
152            catch ( ParseException e )
153            {
154                throw new IllegalArgumentException( "Improperly formatted timestamp for audit log event: " + ts, e);
155            }
156    
157            if ( name.length() > TS_LENGTH )
158            {
159                if ( name.charAt( TS_LENGTH ) != '/' )
160                {
161                    throw new IllegalArgumentException(
162                        "Improperly formatted name for audit log event, no / separator between timestamp and resource: " +
163                            name );
164                }
165            }
166    
167            this.repositoryId = repositoryId;
168        }
169    
170        public AuditEvent( String repoId, String user, String resource, String action )
171        {
172            this.repositoryId = repoId;
173            this.userId = user;
174            this.resource = resource;
175            this.action = action;
176            this.timestamp = Calendar.getInstance().getTime();
177        }
178    
179        public String getRepositoryId()
180        {
181            return repositoryId;
182        }
183    
184        public void setRepositoryId( String repositoryId )
185        {
186            this.repositoryId = repositoryId;
187        }
188    
189        public String getUserId()
190        {
191            return userId;
192        }
193    
194        public void setUserId( String userId )
195        {
196            this.userId = userId;
197        }
198    
199        public String getResource()
200        {
201            return resource;
202        }
203    
204        public void setResource( String resource )
205        {
206            this.resource = resource;
207        }
208    
209        public String getAction()
210        {
211            return action;
212        }
213    
214        public void setAction( String action )
215        {
216            this.action = action;
217        }
218    
219        public String getRemoteIP()
220        {
221            return remoteIP;
222        }
223    
224        public void setRemoteIP( String remoteIP )
225        {
226            this.remoteIP = remoteIP;
227        }
228    
229        public Date getTimestamp()
230        {
231            return timestamp;
232        }
233    
234        public void setTimestamp( Date timestamp )
235        {
236            this.timestamp = timestamp;
237        }
238    
239        public String getFacetId()
240        {
241            return FACET_ID;
242        }
243    
244        public String getName()
245        {
246            // use the hashCode here to make it unique if multiple events occur at a certain timestamp. None of the other
247            // fields is unique on its own
248            return createNameFormat().format( timestamp ) + "/" + Integer.toHexString( hashCode() );
249            // TODO: a simple incremental counter might be better since it will retain ordering, but then we need to do a
250            //  bit of locking...
251        }
252    
253        private static SimpleDateFormat createNameFormat()
254        {
255            SimpleDateFormat fmt = new SimpleDateFormat( TIMESTAMP_FORMAT );
256            fmt.setTimeZone( UTC_TIME_ZONE );
257            return fmt;
258        }
259    
260        public Map<String, String> toProperties()
261        {
262            Map<String, String> properties = new HashMap<String, String>();
263            properties.put( "action", this.action );
264            if ( this.userId != null )
265            {
266                properties.put( "user", this.userId );
267            }
268            if ( this.remoteIP != null )
269            {
270                properties.put( "remoteIP", this.remoteIP );
271            }
272            if ( this.resource != null )
273            {
274                properties.put( "resource", this.resource );
275            }
276            return properties;
277        }
278    
279        public void fromProperties( Map<String, String> properties )
280        {
281            this.action = properties.get( "action" );
282            this.remoteIP = properties.get( "remoteIP" );
283            this.userId = properties.get( "user" );
284            this.resource = properties.get( "resource" );
285        }
286    
287        @Override
288        public boolean equals( Object o )
289        {
290            if ( this == o )
291            {
292                return true;
293            }
294            if ( o == null || getClass() != o.getClass() )
295            {
296                return false;
297            }
298    
299            AuditEvent that = (AuditEvent) o;
300    
301            if ( !action.equals( that.action ) )
302            {
303                return false;
304            }
305            if ( remoteIP != null ? !remoteIP.equals( that.remoteIP ) : that.remoteIP != null )
306            {
307                return false;
308            }
309            if ( repositoryId != null ? !repositoryId.equals( that.repositoryId ) : that.repositoryId != null )
310            {
311                return false;
312            }
313            if ( resource != null ? !resource.equals( that.resource ) : that.resource != null )
314            {
315                return false;
316            }
317            if ( !timestamp.equals( that.timestamp ) )
318            {
319                return false;
320            }
321            if ( userId != null ? !userId.equals( that.userId ) : that.userId != null )
322            {
323                return false;
324            }
325    
326            return true;
327        }
328    
329        @Override
330        public int hashCode()
331        {
332            int result = repositoryId != null ? repositoryId.hashCode() : 0;
333            result = 31 * result + ( userId != null ? userId.hashCode() : 0 );
334            result = 31 * result + ( remoteIP != null ? remoteIP.hashCode() : 0 );
335            result = 31 * result + ( resource != null ? resource.hashCode() : 0 );
336            result = 31 * result + action.hashCode();
337            result = 31 * result + timestamp.hashCode();
338            return result;
339        }
340    
341        @Override
342        public String toString()
343        {
344            final StringBuilder sb = new StringBuilder();
345            sb.append( "AuditEvent" );
346            sb.append( "{repositoryId='" ).append( repositoryId ).append( '\'' );
347            sb.append( ", userId='" ).append( userId ).append( '\'' );
348            sb.append( ", remoteIP='" ).append( remoteIP ).append( '\'' );
349            sb.append( ", resource='" ).append( resource ).append( '\'' );
350            sb.append( ", action='" ).append( action ).append( '\'' );
351            sb.append( ", timestamp=" ).append( timestamp );
352            sb.append( '}' );
353            return sb.toString();
354        }
355    
356    
357    }