1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20
21 package org.apache.axis2.deployment;
22
23 import org.apache.axis2.deployment.repository.util.DeploymentFileData;
24 import org.apache.axis2.deployment.repository.util.WSInfo;
25 import org.apache.axis2.deployment.repository.util.WSInfoList;
26 import org.apache.axis2.deployment.util.Utils;
27 import org.apache.axis2.util.Loader;
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30
31 import java.io.File;
32 import java.io.UnsupportedEncodingException;
33 import java.net.URI;
34 import java.net.URISyntaxException;
35 import java.net.URL;
36 import java.net.URLClassLoader;
37 import java.net.URLDecoder;
38 import java.util.ArrayList;
39 import java.util.Enumeration;
40 import java.util.Iterator;
41 import java.util.Map;
42
43 public class RepositoryListener implements DeploymentConstants {
44 protected static final Log log = LogFactory.getLog(RepositoryListener.class);
45
46 protected DeploymentEngine deploymentEngine;
47
48 /** Reference to a WSInfoList */
49 protected WSInfoList wsInfoList;
50
51 /**
52 * This constructor takes two arguments, a folder name and a reference to Deployment Engine
53 * First, it initializes the system, by loading all the modules in the /modules directory and
54 * then creates a WSInfoList to store information about available modules and services.
55 *
56 * @param deploymentEngine reference to engine registry for updates
57 * @param isClasspath true if this RepositoryListener should scan the classpath for
58 * Modules
59 */
60 public RepositoryListener(DeploymentEngine deploymentEngine, boolean isClasspath) {
61 this.deploymentEngine = deploymentEngine;
62 wsInfoList = new WSInfoList(deploymentEngine);
63 init2(isClasspath);
64 }
65
66 public void init2(boolean isClasspath) {
67 if (!isClasspath) {
68 init();
69 }
70 loadClassPathModules();
71 }
72
73 /** Finds a list of modules in the folder and adds to wsInfoList. */
74 public void checkModules() {
75 File root = deploymentEngine.getModulesDir();
76 File[] files = root.listFiles();
77
78 if (files != null) {
79 for (int i = 0; i < files.length; i++) {
80 File file = files[i];
81 if (isSourceControlDir(file)) {
82 continue;
83 }
84 if (!file.isDirectory()) {
85 if (DeploymentFileData.isModuleArchiveFile(file.getName())) {
86 addFileToDeploy(file, deploymentEngine.getModuleDeployer(),
87 WSInfo.TYPE_MODULE);
88 }
89 } else {
90 if (!"lib".equalsIgnoreCase(file.getName())) {
91 addFileToDeploy(file, deploymentEngine.getModuleDeployer(),
92 WSInfo.TYPE_MODULE);
93 }
94 }
95 }
96 }
97 }
98
99
100 protected boolean isSourceControlDir(File file) {
101 if (file.isDirectory()) {
102 String name = file.getName();
103 if (name.equalsIgnoreCase("CVS") || name.equalsIgnoreCase(".svn")) {
104 return true;
105 }
106 }
107 return false;
108 }
109
110 protected void loadClassPathModules() {
111 ModuleDeployer deployer = deploymentEngine.getModuleDeployer();
112
113 // Find Modules on the class path (i.e. if classpath includes "addressing.mar" then
114 // addressing will be available for engaging)
115
116 ClassLoader loader = Thread.currentThread().getContextClassLoader();
117 try {
118 Enumeration moduleURLs = loader.getResources("META-INF/module.xml");
119 while (moduleURLs.hasMoreElements()) {
120 try {
121 URL url = (URL)moduleURLs.nextElement();
122 URI moduleURI;
123 if (url.getProtocol().equals("file")) {
124 String urlString = url.toString();
125 moduleURI = new URI(urlString.substring(0,
126 urlString.lastIndexOf("/META-INF/module.xml")));
127 } else {
128 // Check if the URL refers to an archive (such as
129 // jar:file:/dir/some.jar!/META-INF/module.xml) and extract the
130 // URL of the archive. In general the protocol will be "jar", but
131 // some containers may use other protocols, e.g. WebSphere uses
132 // "wsjar" (AXIS2-4258).
133 String path = url.getPath();
134 int idx = path.lastIndexOf("!/");
135 if (idx != -1 && path.substring(idx+2).equals("META-INF/module.xml")) {
136 moduleURI = new URI(path.substring(0, idx));
137 if (!moduleURI.getScheme().equals("file")) {
138 continue;
139 }
140 } else {
141 continue;
142 }
143 }
144
145 log.debug("Deploying module from classpath at '" + moduleURI + "'");
146 File f = new File(moduleURI);
147 addFileToDeploy(f, deployer, WSInfo.TYPE_MODULE);
148
149 } catch (URISyntaxException e) {
150 log.info(e);
151 }
152 }
153 } catch (Exception e) {
154 // Oh well, log the problem
155 log.debug(e);
156 }
157
158 String classPath = getLocation();
159
160 if (classPath == null) return;
161
162 int lstindex = classPath.lastIndexOf(File.separatorChar);
163 if (lstindex > 0) {
164 classPath = classPath.substring(0, lstindex);
165 } else {
166 classPath = ".";
167 }
168 File root = new File(classPath);
169 File[] files = root.listFiles();
170 if (files != null) {
171 for (int i = 0; i < files.length; i++) {
172 File file = files[i];
173 if (!file.isDirectory()) {
174 if (DeploymentFileData.isModuleArchiveFile(file.getName())) {
175 //adding modules in the class path
176 addFileToDeploy(file, deployer, WSInfo.TYPE_MODULE);
177 }
178 }
179 }
180 }
181
182 ClassLoader cl = deploymentEngine.getAxisConfig().getModuleClassLoader();
183 while (cl != null) {
184 if (cl instanceof URLClassLoader) {
185 URL[] urls = ((URLClassLoader)cl).getURLs();
186 for (int i = 0; (urls != null) && i < urls.length; i++) {
187 String path = urls[i].getPath();
188 //If it is a drive letter, adjust accordingly.
189 if (path.length() >= 3 && path.charAt(0) == '/' && path.charAt(2) == ':') {
190 path = path.substring(1);
191 }
192 try {
193 path = URLDecoder.decode(path, Utils.defaultEncoding);
194 } catch (UnsupportedEncodingException e) {
195 // Log this?
196 }
197 File file = new File(path.replace('/', File.separatorChar).replace('|', ':'));
198 if (file.isFile()) {
199 if (DeploymentFileData.isModuleArchiveFile(file.getName())) {
200 //adding modules in the class path
201 addFileToDeploy(file, deployer, WSInfo.TYPE_MODULE);
202 }
203 }
204 }
205 }
206 cl = cl.getParent();
207 }
208
209 deploymentEngine.doDeploy();
210 }
211
212 /**
213 * To get the location of the Axis2.jar from that I can drive the location of class path
214 *
215 * @return String (location of the axis2 jar)
216 */
217 protected String getLocation() {
218 try {
219 Class clazz = Loader.loadClass("org.apache.axis2.engine.AxisEngine");
220 java.net.URL url = clazz.getProtectionDomain().getCodeSource().getLocation();
221 String location = url.toString();
222 if (location.startsWith("jar")) {
223 url = ((java.net.JarURLConnection)url.openConnection()).getJarFileURL();
224 location = url.toString();
225 }
226 if (location.startsWith("file")) {
227 File file = Utils.toFile(url);
228 return file.getAbsolutePath();
229 } else {
230 return url.toString();
231 }
232 } catch (Throwable t) {
233 return null;
234 }
235 }
236
237 /** Finds a list of services in the folder and adds to wsInfoList. */
238 public void checkServices() {
239 findServicesInDirectory();
240 loadOtherDirectories();
241 update();
242 }
243
244 /**
245 * First initializes the WSInfoList, then calls checkModule to load all the modules and calls
246 * update() to update the Deployment engine and engine registry.
247 */
248 public void init() {
249 wsInfoList.init();
250 checkModules();
251 deploymentEngine.doDeploy();
252 }
253
254 //This will load the files from the directories
255 // specified by axis2.xml (As <deployer>)
256 private void loadOtherDirectories() {
257 for (Map.Entry<String, Map<String, Deployer>> entry : deploymentEngine.getDeployers().entrySet()) {
258 String directory = entry.getKey();
259 Map<String, Deployer> extensionMap = entry.getValue();
260 for (String extension : extensionMap.keySet()) {
261 findFileForGivenDirectory(directory, extension);
262 }
263 }
264 }
265
266 private void findFileForGivenDirectory(String dir, String extension) {
267 try {
268 File directory = deploymentEngine.getRepositoryDir();
269 String[] strings = dir.split("/");
270 for (int i = 0; i < strings.length; i++) {
271 directory = new File(directory, strings[i]);
272 }
273
274 if (directory.exists()) {
275 File[] files = directory.listFiles();
276 if (files != null && files.length > 0) {
277 for (int i = 0; i < files.length; i++) {
278 File file = files[i];
279 if (isSourceControlDir(file)) {
280 continue;
281 }
282 if (!file.isDirectory() && extension
283 .equals(DeploymentFileData.getFileExtension(file.getName()))) {
284 addFileToDeploy(file,
285 deploymentEngine.getDeployer(dir, extension),
286 WSInfo.TYPE_CUSTOM);
287 }
288 }
289 }
290 }
291 } catch (Exception e) {
292 //need to log the exception
293 }
294 }
295
296 /** Searches a given folder for jar files and adds them to a list in the WSInfolist class. */
297 protected void findServicesInDirectory() {
298 File root = deploymentEngine.getServicesDir();
299 File[] files = root.listFiles();
300
301 if (files != null && files.length > 0) {
302 for (int i = 0; i < files.length; i++) {
303 File file = files[i];
304 if (isSourceControlDir(file)) {
305 continue;
306 }
307 if (!file.isDirectory()) {
308 if (DeploymentFileData.isServiceArchiveFile(file.getName())) {
309 addFileToDeploy(file, deploymentEngine.getServiceDeployer(),
310 WSInfo.TYPE_SERVICE);
311 } else {
312 String ext = DeploymentFileData.getFileExtension(file.getName());
313 Deployer deployer = deploymentEngine.getDeployerForExtension(ext);
314 // If we found a deployer for this type of file, use it. Otherwise
315 // ignore the file.
316 if (deployer != null) {
317 addFileToDeploy(file, deployer, WSInfo.TYPE_SERVICE);
318 }
319 }
320 } else {
321 if (!"lib".equalsIgnoreCase(file.getName())) {
322 addFileToDeploy(file, deploymentEngine.getServiceDeployer(),
323 WSInfo.TYPE_SERVICE);
324 }
325 }
326 }
327 }
328 }
329
330 /** Method invoked from the scheduler to start the listener. */
331 public void startListener() {
332 checkServices();
333 // update();
334 }
335
336 /** Updates WSInfoList object. */
337 public void update() {
338 wsInfoList.update();
339 }
340
341 public void updateRemote() throws Exception {
342 findServicesInDirectory();
343 update();
344 }
345
346 public void addFileToDeploy(File file, Deployer deployer, int type) {
347 wsInfoList.addWSInfoItem(file, deployer, type);
348 }
349 }