View Javadoc

1   /*
2   Copyright (c) 2006, University of Tromsø
3   All rights reserved.
4   
5   Redistribution and use in source and binary forms, with or without 
6   modification, are permitted provided that the following conditions are met:
7   
8    * Redistributions of source code must retain the above copyright notice, this list 
9      of conditions and the following disclaimer.
10  
11   * Redistributions in binary form must reproduce the above copyright notice, this 
12     list of conditions and the following disclaimer in the documentation and/or other 
13     materials provided with the distribution.
14  
15   * Neither the name of the University of Tromsø nor the names of its contributors may 
16     be used to endorse or promote products derived from this software without specific 
17     prior written permission.
18  
19  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
20  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
21  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
22  SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
23  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
24  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
25  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
26  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
27  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 
28  DAMAGE.
29  */
30  
31  package argos.metadata;
32  
33  import java.io.ByteArrayInputStream;
34  import java.io.File;
35  import java.io.IOException;
36  import java.io.Serializable;
37  import java.util.ArrayList;
38  import java.util.List;
39  import java.util.logging.Level;
40  import java.util.logging.Logger;
41  
42  import javax.xml.parsers.DocumentBuilder;
43  import javax.xml.parsers.DocumentBuilderFactory;
44  import javax.xml.parsers.ParserConfigurationException;
45  
46  import org.w3c.dom.Document;
47  import org.w3c.dom.Element;
48  import org.w3c.dom.NodeList;
49  import org.xml.sax.SAXException;
50  
51  import argos.Argos;
52  import argos.deploy.JarClassloader;
53  import argos.deploy.JarResource;
54  import argos.naming.NamingService;
55  import argos.util.Util;
56  import argos.util.graph.Node;
57  import argos.config.Config;
58  
59  /**
60   * Created on 05.jul.2006
61   * 
62   * @author Dan Peder Eriksen
63   */
64  public class ServiceMetaInfo extends Running implements Serializable {
65  	public static final long serialVersionUID = 23947239478293479L;
66  	
67  	private static final Logger logger = Logger.getLogger(ServiceMetaInfo.class.getName());
68  	
69  	private File orginalFile;
70  	private File tempFile;
71  	private File tempDir;
72  	private String remoteFile;
73  	private double version;
74  	private String soapEndPoint;
75  	private List<File> libraries;
76  	private List<String> dependencies;
77  	private List<ComponentMetaInfo> componentMetaInfo;
78  	private transient JarClassloader loader;
79  	
80  	public ServiceMetaInfo(File file) throws ParserConfigurationException, IOException, SAXException, 
81  			InformationMissingException {
82  		super();
83  		this.orginalFile = file;
84  		
85  		componentMetaInfo = new ArrayList<ComponentMetaInfo>();
86  		dependencies = new ArrayList<String>();
87  		libraries = new ArrayList<File>();
88  		
89  		// Load
90  		JarResource jar = new JarResource(file);
91  		byte[] bytes = jar.getResource(Config.DEPLOY_DESCRIPTOR);
92  		if(bytes == null) {
93  			throw new InformationMissingException("Deploy descriptor (deploy.xml) is missing in " + 
94  					file.getName() + ".");
95  		}
96  		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
97  		DocumentBuilder parser = factory.newDocumentBuilder();
98  		Document document = parser.parse(new ByteArrayInputStream(bytes));
99  		Element service = document.getDocumentElement();
100 		
101 		
102 		// Service name
103 		name = service.getAttribute("name");
104 		if(name == null) {
105 			throw new InformationMissingException("The service name is missing");
106 		}
107 		
108 		//Soap end point
109 		soapEndPoint = service.getAttribute("SoapEndPoint");
110 		
111 		//Dependencies
112 		NodeList elements = service.getElementsByTagName("depend");
113 		for(int i = 0; i < elements.getLength(); i++) {
114 			Element element = (Element) elements.item(i);
115 			Element parent = (Element) element.getParentNode();
116 			if(!service.equals(parent)) {
117 				continue;
118 			}
119 			String on = element.getAttribute("on");
120 			if(on == null) {
121 				throw new InformationMissingException("Dependency tag is missing on attribute");
122 			}
123 			dependencies.add(on);
124 		}
125 		
126 		
127 		// Service version
128 		String versionTemp = service.getAttribute("version");
129 		if(versionTemp == null) {
130 			throw new InformationMissingException("The service version is missing");
131 		}
132 		else {
133 			version = Double.parseDouble(versionTemp);
134 		}
135 		
136 		// Deploy
137 		elements = service.getElementsByTagName("deploy");
138 		if(elements.getLength() != 1) {
139 			throw new InformationMissingException("There can only be ONE deploy tag");
140 		}
141 		Element deploy = (Element) elements.item(0);
142 		remoteFile = deploy.getAttribute("remote");
143 		
144 		NodeList components = service.getElementsByTagName("component");
145 		for(int i = 0; i < components.getLength(); i++) {
146 			componentMetaInfo.add(new ComponentMetaInfo(this, (Element) components.item(i)));
147 		}
148 	}
149 	
150 	public void setupDependencies(List<ServiceMetaInfo> services) throws DependencyMissingException {
151 		for(String depends : dependencies) {
152 			boolean found = false;
153 			for(ServiceMetaInfo service : services) {
154 				if(depends.equals(service.getName())) {
155 					thisDependsOn.add(service);
156 					service.dependsOnThis.add(this);
157 					found = true;
158 					break;
159 				}
160 			}
161 			if(!found) {
162 				ServiceMetaInfo service = NamingService.getInstance().getServiceByName(depends, false);
163 				if(service == null) {
164 					throw new DependencyMissingException("missing dependency " + depends + ".");
165 				}
166 			}
167 		}
168 		
169 		
170 		try {
171 			for(ComponentMetaInfo meta : componentMetaInfo) {
172 				meta.setupDependencies(services);
173 			}
174 		}
175 		catch(DependencyMissingException e) {
176 			for(ComponentMetaInfo meta : componentMetaInfo) {
177 				
178 				meta.resetDependencies();
179 			}
180 			throw e;
181 		}
182 	}
183 	
184 	public void setClassLoader(JarClassloader loader) {
185 		this.loader = loader;
186 	}
187 	
188 	public JarClassloader getClassLoader() {
189 		return loader;
190 	}
191 	
192 	public void addComponentMetaInfo(ComponentMetaInfo component) {
193 		componentMetaInfo.add(component);
194 	}
195 	
196 	public List<ComponentMetaInfo> getComponentMetaInfo() {
197 		List<ComponentMetaInfo> list = new ArrayList<ComponentMetaInfo>();
198 		for(ComponentMetaInfo temp : componentMetaInfo) {
199 			list.add(temp);
200 		}
201 		return list;
202 	}
203 	
204 	public List<File> getLibraries() {
205 		List<File> list = new ArrayList<File>();
206 		for(File temp : libraries) {
207 			list.add(temp);
208 		}
209 		return list;
210 	}
211 	
212 	public boolean createTempFile() {
213 		String dir = Argos.TEMP_DIR + "/" + getName() + System.currentTimeMillis();
214 		tempDir = new File(dir);
215 		tempDir.mkdir();
216 		tempFile = new File(dir + "/" + orginalFile.getName());
217 		//Copy file
218 		try {
219 			Util.copyFile(orginalFile, tempFile);
220 		}
221 		catch (IOException e) {
222 			logger.log(Level.SEVERE, "Unable to copy " + orginalFile.getName() + " to temp dir: " + 
223 					e.getMessage(), e);
224 			Util.cleanDir(tempDir);
225 			return false;
226 		}
227 		//Libraries
228 		File libDir = new File(dir + "/lib");
229 		libDir.mkdir();
230 		try {
231 			libraries = Util.extractFromJar(orginalFile, "lib", dir, false);
232 			if(libraries.isEmpty()) {
233 				libDir.delete();
234 			}
235 		}
236 		catch(IOException e) {
237 			logger.log(Level.SEVERE, "Unable to extract files from " + orginalFile.getName() + 
238 					" to temp dir: " + e.getMessage(), e);
239 			Util.cleanDir(tempDir);
240 			return false;
241 		}
242 		return true;
243 	}
244 	
245 	public File getTempDir() {
246 		return tempDir;
247 	}
248 
249 	public File getTempFile() {
250 		return tempFile;
251 	}
252 	
253 	public ComponentMetaInfo getComponentMetaInfo(String componentName) {
254 		for(ComponentMetaInfo comp : componentMetaInfo) {
255 			if(comp.getName().equals(componentName)) {
256 				return comp;
257 			}
258 		}
259 		logger.severe("Unable to find component " + componentName);
260 		return null;
261 	}
262 	
263 	public List<String> getDependencies() {
264 		return dependencies;
265 	}
266 	
267 	public String getRemoteFile() {
268 		return remoteFile;
269 	}
270 	
271 	public double getVersion() {
272 		return version;
273 	}
274 	
275 	public File getFile() {
276 		return orginalFile;
277 	}
278 	
279 	public String getSoapEndPoint() {
280 		return soapEndPoint;
281 	}
282 	
283 	public void cleanUp() {
284 		Util.cleanDir(tempDir);
285 		tempDir.delete();
286 	}
287 	
288 	public static void cleanUpTempFolder() {
289 		Util.cleanDir(new File(Argos.TEMP_DIR));
290 	}
291 
292 	@Override
293 	public boolean equals(Object o) {
294 		if(o instanceof ServiceMetaInfo) {
295 			ServiceMetaInfo service = (ServiceMetaInfo) o;
296 			return service.hashCode() == hashCode();
297 		}
298 		return false;
299 	}
300 	
301 	@Override
302 	public int hashCode() {
303 		return name.hashCode();
304 	}
305 	
306 	@Override
307 	public String toString() {
308 		return getName();
309 	}
310 	
311 	public boolean dependsOn(ServiceMetaInfo service) {
312 		for(String s : dependencies) {
313 			ServiceMetaInfo temp = NamingService.getInstance().getServiceByName(s);
314 			if(temp != null) {
315 				if(service == temp) {
316 					return true;
317 				}
318 				else {
319 					if(temp.dependsOn(service)) {
320 						return true;
321 					}
322 				}
323 			}
324 		}
325 		return false;
326 	}
327 	
328 	@Override
329 	public int compareTo(Node node) {
330 		if(name.startsWith(Config.BANG_BANG) && !node.getName().startsWith(Config.BANG_BANG)) {
331 			return -1;
332 		}
333 		else if(!name.startsWith(Config.BANG_BANG) && node.getName().startsWith(Config.BANG_BANG)) {
334 			return 1;
335 		}
336 		else {
337 			return super.compareTo(node);
338 		}
339 	}
340 }