Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
ExternalRepositoriesReloadableWebappLoader |
|
| 3.5;3,5 |
1 | package org.apache.tomcat.maven.common.run; | |
2 | ||
3 | /* | |
4 | * Licensed to the Apache Software Foundation (ASF) under one | |
5 | * or more contributor license agreements. See the NOTICE file | |
6 | * distributed with this work for additional information | |
7 | * regarding copyright ownership. The ASF licenses this file | |
8 | * to you under the Apache License, Version 2.0 (the | |
9 | * "License"); you may not use this file except in compliance | |
10 | * with the License. You may obtain a copy of the License at | |
11 | * | |
12 | * http://www.apache.org/licenses/LICENSE-2.0 | |
13 | * | |
14 | * Unless required by applicable law or agreed to in writing, | |
15 | * software distributed under the License is distributed on an | |
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
17 | * KIND, either express or implied. See the License for the | |
18 | * specific language governing permissions and limitations | |
19 | * under the License. | |
20 | */ | |
21 | ||
22 | import org.apache.catalina.loader.WebappLoader; | |
23 | import org.apache.maven.plugin.logging.Log; | |
24 | ||
25 | import java.io.File; | |
26 | import java.net.MalformedURLException; | |
27 | import java.net.URL; | |
28 | import java.util.Date; | |
29 | import java.util.HashMap; | |
30 | import java.util.Map; | |
31 | ||
32 | /** | |
33 | * A {@linkplain WebappLoader} implementation that allows scanning for changes to project classpath in support of | |
34 | * context reloads. | |
35 | * | |
36 | * @author Ryan Connolly | |
37 | * @since 2.0 | |
38 | */ | |
39 | public class ExternalRepositoriesReloadableWebappLoader | |
40 | extends WebappLoader | |
41 | { | |
42 | ||
43 | /** | |
44 | * Last modification times of all jar and class files. | |
45 | */ | |
46 | 0 | private Map<String, Long> modificationTimeMap = new HashMap<String, Long>(); |
47 | ||
48 | private Log log; | |
49 | ||
50 | /** | |
51 | * Default Constructor. | |
52 | */ | |
53 | public ExternalRepositoriesReloadableWebappLoader() | |
54 | { | |
55 | 0 | super(); |
56 | 0 | } |
57 | ||
58 | ||
59 | /** | |
60 | * Convenience Constructor allows setting of a parent ClassLoader. | |
61 | * | |
62 | * @param parent the ClassLoader instance to set as this Loader's parent ClassLoader. | |
63 | */ | |
64 | public ExternalRepositoriesReloadableWebappLoader( ClassLoader parent, Log log ) | |
65 | { | |
66 | 0 | super( parent ); |
67 | 0 | this.log = log; |
68 | 0 | } |
69 | ||
70 | /** | |
71 | * {@inheritDoc} | |
72 | */ | |
73 | @Override | |
74 | public void addRepository( String repository ) | |
75 | { | |
76 | 0 | super.addRepository( repository ); |
77 | try | |
78 | { | |
79 | 0 | File file = new File( new URL( repository ).getPath().replaceAll( "%20", " " ) ); |
80 | 0 | if ( file.isDirectory() ) |
81 | { | |
82 | 0 | addClassDirectory( file ); |
83 | } | |
84 | 0 | else if ( file.isFile() && file.getName().endsWith( ".jar" ) ) |
85 | { | |
86 | 0 | addFile( file ); |
87 | } | |
88 | } | |
89 | 0 | catch ( MalformedURLException muex ) |
90 | { | |
91 | 0 | throw new RuntimeException( muex ); |
92 | 0 | } |
93 | 0 | } |
94 | ||
95 | /** | |
96 | * Tracks modification times of files in the given class directory. | |
97 | * | |
98 | * @param directory the File directory to track modification times for. | |
99 | */ | |
100 | private void addClassDirectory( File directory ) | |
101 | { | |
102 | 0 | for ( File file : directory.listFiles() ) |
103 | { | |
104 | 0 | if ( file.isDirectory() ) |
105 | { | |
106 | //remember also directory last modification time | |
107 | 0 | addFile( file ); |
108 | 0 | addClassDirectory( file ); |
109 | } | |
110 | 0 | else if ( file.isFile() ) |
111 | { | |
112 | 0 | addFile( file ); |
113 | } | |
114 | } | |
115 | 0 | } |
116 | ||
117 | /** | |
118 | * Tracks last modification time of the given File. | |
119 | * | |
120 | * @param file the File for which to track last modification time. | |
121 | */ | |
122 | private void addFile( File file ) | |
123 | { | |
124 | 0 | modificationTimeMap.put( file.getAbsolutePath(), file.lastModified() ); |
125 | 0 | } |
126 | ||
127 | /** | |
128 | * Check if {@link WebappLoader} says modified(), if not then check files from added repositories. | |
129 | */ | |
130 | @Override | |
131 | public boolean modified() | |
132 | { | |
133 | 0 | boolean modified = super.modified(); |
134 | 0 | if ( !modified ) |
135 | { | |
136 | 0 | if ( log != null ) |
137 | { | |
138 | 0 | log.debug( "classPath scanning started at " + new Date().toString() ); |
139 | } | |
140 | 0 | for ( Map.Entry<String, Long> entry : modificationTimeMap.entrySet() ) |
141 | { | |
142 | 0 | String key = entry.getKey(); |
143 | 0 | File file = new File( key ); |
144 | 0 | if ( file.exists() ) |
145 | { | |
146 | // file could be deleted. | |
147 | 0 | Long savedLastModified = modificationTimeMap.get( key ); |
148 | 0 | if ( file.lastModified() > savedLastModified ) |
149 | { | |
150 | 0 | modified = true; |
151 | 0 | modificationTimeMap.put( key, file.lastModified() ); |
152 | ||
153 | // directory last modification time can change when some class, | |
154 | // jar or subdirectory was added or deleted. | |
155 | 0 | if ( file.isDirectory() ) |
156 | { | |
157 | 0 | addClassDirectory( file ); |
158 | } | |
159 | } | |
160 | } | |
161 | 0 | } |
162 | } | |
163 | 0 | if ( log != null ) |
164 | { | |
165 | 0 | log.debug( "context " + modified + " at " + new Date().toString() ); |
166 | } | |
167 | 0 | return modified; |
168 | } | |
169 | ||
170 | } |