View Javadoc

1   /* ModeShape (http://www.modeshape.org)" target="alexandria_uri">http://www.modeshape.org) 
2      See the COPYRIGHT.txt file distributed with this work for information 
3      regarding copyright ownership. Some portions may be licensed 
4      to Red Hat, Inc. under one or more contributor license agreements. 
5      See the AUTHORS.txt file in the distribution for a full listing of individual contributors.  
6      ModeShape is free software. Unless otherwise indicated, all code in 
7      ModeShape is licensed to you under the terms of the GNU Lesser General Public License as 
8      published by the Free Software Foundation; either version 2.1 of 
9      the License, or (at your option) any later version. 
10     ModeShape is distributed in the hope that it will be useful, 
11     but WITHOUT ANY WARRANTY; without even the implied warranty of 
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
13     Lesser General Public License for more details. 
14     You should have received a copy of the GNU Lesser General Public 
15     License along with this software; if not, write to the Free 
16     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 
17     02110-1301 USA, or see the	FSF site: http://www.fsf.org. 
18   */
19  package org.modeshape.rhq.plugin;
20  
21  import java.io.File;
22  import java.io.InputStream;
23  import java.util.HashMap;
24  import java.util.HashSet;
25  import java.util.List;
26  import java.util.Map;
27  import java.util.Set;
28  
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  import org.jboss.deployers.spi.management.ManagementView;
32  import org.jboss.managed.api.ComponentType;
33  import org.jboss.managed.api.ManagedComponent;
34  import org.jboss.managed.api.ManagedProperty;
35  import org.modeshape.rhq.plugin.objects.ExecutedOperationResultImpl;
36  import org.modeshape.rhq.plugin.objects.ExecutedResult;
37  import org.modeshape.rhq.plugin.util.ModeShapeManagementView;
38  import org.modeshape.rhq.plugin.util.PluginConstants;
39  import org.modeshape.rhq.plugin.util.ProfileServiceUtil;
40  import org.rhq.core.domain.configuration.Configuration;
41  import org.rhq.core.domain.configuration.ConfigurationUpdateStatus;
42  import org.rhq.core.domain.configuration.definition.ConfigurationTemplate;
43  import org.rhq.core.domain.content.PackageDetailsKey;
44  import org.rhq.core.domain.content.PackageType;
45  import org.rhq.core.domain.content.transfer.DeployPackageStep;
46  import org.rhq.core.domain.content.transfer.DeployPackagesResponse;
47  import org.rhq.core.domain.content.transfer.RemovePackagesResponse;
48  import org.rhq.core.domain.content.transfer.ResourcePackageDetails;
49  import org.rhq.core.domain.measurement.AvailabilityType;
50  import org.rhq.core.domain.measurement.MeasurementReport;
51  import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
52  import org.rhq.core.domain.resource.ResourceType;
53  import org.rhq.core.pluginapi.configuration.ConfigurationFacet;
54  import org.rhq.core.pluginapi.configuration.ConfigurationUpdateReport;
55  import org.rhq.core.pluginapi.content.ContentFacet;
56  import org.rhq.core.pluginapi.content.ContentServices;
57  import org.rhq.core.pluginapi.content.version.PackageVersions;
58  import org.rhq.core.pluginapi.inventory.CreateChildResourceFacet;
59  import org.rhq.core.pluginapi.inventory.DeleteResourceFacet;
60  import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
61  import org.rhq.core.pluginapi.inventory.ResourceComponent;
62  import org.rhq.core.pluginapi.inventory.ResourceContext;
63  import org.rhq.core.pluginapi.measurement.MeasurementFacet;
64  import org.rhq.core.pluginapi.operation.OperationFacet;
65  import org.rhq.core.pluginapi.operation.OperationResult;
66  import org.rhq.plugins.jbossas5.ProfileServiceComponent;
67  
68  /**
69   * This class implements required RHQ interfaces and provides common logic used
70   * by all MetaMatrix components.
71   */
72  @SuppressWarnings( { "unchecked" })
73  public abstract class Facet implements
74  		ProfileServiceComponent<ResourceComponent>, MeasurementFacet,
75  		OperationFacet, ConfigurationFacet, ContentFacet, DeleteResourceFacet,
76  		CreateChildResourceFacet {
77  
78  	protected final Log LOG = LogFactory
79  			.getLog(PluginConstants.DEFAULT_LOGGER_CATEGORY);
80  
81  	/**
82  	 * Represents the resource configuration of the custom product being
83  	 * managed.
84  	 */
85  	protected Configuration resourceConfiguration;
86  
87  	/**
88  	 * All AMPS plugins are stateful - this context contains information that
89  	 * your resource component can use when performing its processing.
90  	 */
91  	protected ResourceContext<?> resourceContext;
92  
93  	protected String name;
94  
95  	private String identifier;
96  
97  	protected String componentType;
98  
99  	protected boolean isAvailable = false;
100 
101 	private final Log log = LogFactory.getLog(this.getClass());
102 
103 	/**
104 	 * The name of the ManagedDeployment (e.g.:
105 	 * C:/opt/jboss-5.0.0.GA/server/default/deploy/foo.vdb).
106 	 */
107 	protected String deploymentName;
108 
109 	private PackageVersions versions = null;
110 
111 	/**
112 	 * Name of the backing package type that will be used when discovering
113 	 * packages. This corresponds to the name of the package type defined in the
114 	 * plugin descriptor. For simplicity, the package type for VDBs is called
115 	 * "vdb". This is still unique within the context of the parent resource
116 	 * type and lets this class use the same package type name in both cases.
117 	 */
118 	private static final String PKG_TYPE_VDB = "vdb";
119 
120 	/**
121 	 * Architecture string used in describing discovered packages.
122 	 */
123 	private static final String ARCHITECTURE = "noarch";
124 
125 	abstract String getComponentType();
126 
127 	/**
128 	 * This is called when your component has been started with the given
129 	 * context. You normally initialize some internal state of your component as
130 	 * well as attempt to make a stateful connection to your managed resource.
131 	 * 
132 	 * @param context
133 	 * 
134 	 * @see ResourceComponent#start(ResourceContext)
135 	 */
136 	public void start(ResourceContext context) {
137 		resourceContext = context;
138 		deploymentName = context.getResourceKey();
139 	}
140 
141 	/**
142 	 * This is called when the component is being stopped, usually due to the
143 	 * plugin container shutting down. You can perform some cleanup here; though
144 	 * normally not much needs to be done here.
145 	 * 
146 	 * @see ResourceComponent#stop()
147 	 */
148 	public void stop() {
149 		this.isAvailable = false;
150 	}
151 
152 	/**
153 	 * @return the resourceConfiguration
154 	 */
155 	public Configuration getResourceConfiguration() {
156 		return resourceConfiguration;
157 	}
158 
159 	/**
160 	 * @param resourceConfiguration
161 	 *            the resourceConfiguration to set
162 	 */
163 	public void setResourceConfiguration(Configuration resourceConfiguration) {
164 		this.resourceConfiguration = resourceConfiguration;
165 	}
166 
167 	public String componentType() {
168 		return name;
169 	}
170 
171 	protected void setComponentName(String componentName) {
172 		this.name = componentName;
173 	}
174 
175 	public String getComponentIdentifier() {
176 		return identifier;
177 	}
178 
179 	protected void setComponentIdentifier(String identifier) {
180 		this.identifier = identifier;
181 	}
182 
183 	protected void setOperationArguments(String name,
184 			Configuration configuration, Map<String, Object> argumentMap) {
185 		// moved this logic up to the associated implemented class
186 		throw new InvalidPluginConfigurationException(
187 				"Not implemented on component type " + this.getComponentType()
188 						+ " named " + this.name);
189 
190 	}
191 
192 	protected void setMetricArguments(String name, Configuration configuration,
193 			Map<String, Object> argumentMap) {
194 		// moved this logic up to the associated implemented class
195 		throw new InvalidPluginConfigurationException(
196 				"Not implemented on component type " + this.getComponentType()
197 						+ " named " + this.name);
198 
199 	}
200 
201 	protected void execute(final ExecutedResult result, final Map valueMap) {
202 		ModeShapeManagementView mv = new ModeShapeManagementView();
203 
204 		mv.executeOperation(getConnection(), result, valueMap);
205 
206 	}
207 
208 	/*
209 	 * (non-Javadoc) This method is called by JON to check the availability of
210 	 * the inventoried component on a time scheduled basis
211 	 * 
212 	 * @see org.rhq.core.pluginapi.inventory.ResourceComponent#getAvailability()
213 	 */
214 	public AvailabilityType getAvailability() {
215 
216 		LOG.debug("Checking availability of  " + identifier); //$NON-NLS-1$
217 
218 		return AvailabilityType.UP;
219 	}
220 
221 	/**
222 	 * Helper method that indicates the latest status based on the last
223 	 * getAvailabilit() call.
224 	 * 
225 	 * @return true if the resource is available
226 	 */
227 	protected boolean isAvailable() {
228 		return true;
229 	}
230 
231 	/**
232 	 * The plugin container will call this method when your resource component
233 	 * has been scheduled to collect some measurements now. It is within this
234 	 * method that you actually talk to the managed resource and collect the
235 	 * measurement data that is has emitted.
236 	 * 
237 	 * @see MeasurementFacet#getValues(MeasurementReport, Set)
238 	 */
239 	public abstract void getValues(MeasurementReport arg0,
240 			Set<MeasurementScheduleRequest> arg1) throws Exception;
241 
242 	/**
243 	 * The plugin container will call this method when it wants to invoke an
244 	 * operation on your managed resource. Your plugin will connect to the
245 	 * managed resource and invoke the analogous operation in your own custom
246 	 * way.
247 	 * 
248 	 * @see OperationFacet#invokeOperation(String, Configuration)
249 	 */
250 	public OperationResult invokeOperation(String name,
251 			Configuration configuration) {
252 		Map valueMap = new HashMap<String, Object>();
253 
254 		Set operationDefinitionSet = this.resourceContext.getResourceType()
255 				.getOperationDefinitions();
256 
257 		ExecutedResult result = new ExecutedOperationResultImpl(this
258 				.getComponentType(), name, operationDefinitionSet);
259 
260 		setOperationArguments(name, configuration, valueMap);
261 
262 		execute(result, valueMap);
263 
264 		return ((ExecutedOperationResultImpl) result).getOperationResult();
265 
266 	}
267 
268 	/**
269 	 * The plugin container will call this method and it needs to obtain the
270 	 * current configuration of the managed resource. Your plugin will obtain
271 	 * the managed resource's configuration in your own custom way and populate
272 	 * the returned Configuration object with the managed resource's
273 	 * configuration property values.
274 	 * 
275 	 * @see ConfigurationFacet#loadResourceConfiguration()
276 	 */
277 	public Configuration loadResourceConfiguration() {
278 		// here we simulate the loading of the managed resource's configuration
279 
280 		if (resourceConfiguration == null) {
281 			// for this example, we will create a simple dummy configuration to
282 			// start with.
283 			// note that it is empty, so we're assuming there are no required
284 			// configs in the plugin descriptor.
285 			resourceConfiguration = this.resourceContext
286 					.getPluginConfiguration();
287 		}
288 
289 		Configuration config = resourceConfiguration;
290 
291 		return config;
292 	}
293 
294 	/**
295 	 * The plugin container will call this method when it has a new
296 	 * configuration for your managed resource. Your plugin will re-configure
297 	 * the managed resource in your own custom way, setting its configuration
298 	 * based on the new values of the given configuration.
299 	 * 
300 	 * @see ConfigurationFacet#updateResourceConfiguration(ConfigurationUpdateReport)
301 	 */
302 	public void updateResourceConfiguration(ConfigurationUpdateReport report) {
303 
304 		resourceConfiguration = report.getConfiguration().deepCopy();
305 
306 		Configuration resourceConfig = report.getConfiguration();
307 
308 		ManagementView managementView = null;
309 		ComponentType componentType = null;
310 
311 		ManagedComponent managedComponent = null;
312 		report.setStatus(ConfigurationUpdateStatus.SUCCESS);
313 		try {
314 
315 			managementView = getConnection().getManagementView();
316 			managedComponent = managementView.getComponent(this.name,
317 					componentType);
318 			Map<String, ManagedProperty> managedProperties = managedComponent
319 					.getProperties();
320 
321 			ProfileServiceUtil.convertConfigurationToManagedProperties(
322 					managedProperties, resourceConfig, resourceContext
323 							.getResourceType());
324 
325 			try {
326 				managementView.updateComponent(managedComponent);
327 			} catch (Exception e) {
328 				LOG.error("Unable to update component ["
329 						+ managedComponent.getName() + "] of type "
330 						+ componentType + ".", e);
331 				report.setStatus(ConfigurationUpdateStatus.FAILURE);
332 				report.setErrorMessageFromThrowable(e);
333 			}
334 		} catch (Exception e) {
335 			LOG.error("Unable to process update request", e);
336 			report.setStatus(ConfigurationUpdateStatus.FAILURE);
337 			report.setErrorMessageFromThrowable(e);
338 		}
339 	}
340 
341 	/**
342 	 * @return Map<String, ManagedProperty>
343 	 * @throws Exception
344 	 */
345 	protected Map<String, ManagedProperty> getManagedProperties()
346 			throws Exception {
347 		return null;
348 	}
349 
350 	/**
351 	 * @param managedComponent
352 	 * @throws Exception
353 	 */
354 	protected void updateComponent(ManagedComponent managedComponent)
355 			throws Exception {
356 		log.trace("Updating " + this.name + " with component "
357 				+ managedComponent.toString() + "...");
358 		ManagementView managementView = getConnection().getManagementView();
359 		managementView.updateComponent(managedComponent);
360 
361 	}
362 
363 	@Override
364 	public void deleteResource() throws Exception {
365 
366 		// DeploymentManager deploymentManager = ProfileServiceUtil
367 		// .getDeploymentManager();
368 		//
369 		// log.debug("Stopping deployment [" + this.deploymentName + "]...");
370 		// DeploymentProgress progress = deploymentManager
371 		// .stop(this.deploymentName);
372 		// DeploymentStatus stopStatus = DeploymentUtils.run(progress);
373 		// if (stopStatus.isFailed()) {
374 		// log.error("Failed to stop deployment '" + this.deploymentName
375 		// + "'.", stopStatus.getFailure());
376 		// throw new Exception("Failed to stop deployment '"
377 		// + this.deploymentName + "' - cause: "
378 		// + stopStatus.getFailure());
379 		// }
380 		// log.debug("Removing deployment [" + this.deploymentName + "]...");
381 		// progress = deploymentManager.remove(this.deploymentName);
382 		// DeploymentStatus removeStatus = DeploymentUtils.run(progress);
383 		// if (removeStatus.isFailed()) {
384 		// log.error("Failed to remove deployment '" + this.deploymentName
385 		// + "'.", removeStatus.getFailure());
386 		// throw new Exception("Failed to remove deployment '"
387 		// + this.deploymentName + "' - cause: "
388 		// + removeStatus.getFailure());
389 		// }
390 
391 	}
392 
393 	@Override
394 	public DeployPackagesResponse deployPackages(
395 			Set<ResourcePackageDetails> packages,
396 			ContentServices contentServices) {
397 		return null;
398 	}
399 
400 	@Override
401 	public Set<ResourcePackageDetails> discoverDeployedPackages(PackageType arg0) {
402 
403 		File deploymentFile = null;
404 
405 		if (this.deploymentName != null) {
406 			deploymentFile = new File(deploymentName.substring(7));
407 		}
408 
409 		if (deploymentFile == null || !deploymentFile.exists())
410 			throw new IllegalStateException("Deployment file '"
411 					+ deploymentFile + "' for " + this.getComponentType()
412 					+ " does not exist.");
413 
414 		String fileName = deploymentFile.getName();
415 		org.rhq.core.pluginapi.content.version.PackageVersions packageVersions = loadPackageVersions();
416 		String version = packageVersions.getVersion(fileName);
417 		if (version == null) {
418 			// This is either the first time we've discovered this VDB, or
419 			// someone purged the PC's data dir.
420 			version = "1.0";
421 			packageVersions.putVersion(fileName, version);
422 			packageVersions.saveToDisk();
423 		}
424 
425 		// Package name is the deployment's file name (e.g. foo.ear).
426 		PackageDetailsKey key = new PackageDetailsKey(fileName, version,
427 				PKG_TYPE_VDB, ARCHITECTURE);
428 		ResourcePackageDetails packageDetails = new ResourcePackageDetails(key);
429 		packageDetails.setFileName(fileName);
430 		packageDetails.setLocation(deploymentFile.getPath());
431 		if (!deploymentFile.isDirectory())
432 			packageDetails.setFileSize(deploymentFile.length());
433 		packageDetails.setFileCreatedDate(null);
434 		Set<ResourcePackageDetails> packages = new HashSet<ResourcePackageDetails>();
435 		packages.add(packageDetails);
436 
437 		return packages;
438 	}
439 
440 	@Override
441 	public List<DeployPackageStep> generateInstallationSteps(
442 			ResourcePackageDetails arg0) {
443 		return null;
444 	}
445 
446 	@Override
447 	public RemovePackagesResponse removePackages(
448 			Set<ResourcePackageDetails> arg0) {
449 		return null;
450 	}
451 
452 	@Override
453 	public InputStream retrievePackageBits(ResourcePackageDetails packageDetails) {
454 		return null;
455 	}
456 
457 	protected static Configuration getDefaultPluginConfiguration(
458 			ResourceType resourceType) {
459 		ConfigurationTemplate pluginConfigDefaultTemplate = resourceType
460 				.getPluginConfigurationDefinition().getDefaultTemplate();
461 		return (pluginConfigDefaultTemplate != null) ? pluginConfigDefaultTemplate
462 				.createConfiguration()
463 				: new Configuration();
464 	}
465 
466 	/**
467 	 * Returns an instantiated and loaded versions store access point.
468 	 * 
469 	 * @return will not be <code>null</code>
470 	 */
471 	private org.rhq.core.pluginapi.content.version.PackageVersions loadPackageVersions() {
472 		if (this.versions == null) {
473 			ResourceType resourceType = resourceContext.getResourceType();
474 			String pluginName = resourceType.getPlugin();
475 			File dataDirectoryFile = resourceContext.getDataDirectory();
476 			dataDirectoryFile.mkdirs();
477 			String dataDirectory = dataDirectoryFile.getAbsolutePath();
478 			log.trace("Creating application versions store with plugin name ["
479 					+ pluginName + "] and data directory [" + dataDirectory
480 					+ "]");
481 			this.versions = new PackageVersions(pluginName, dataDirectory);
482 			this.versions.loadFromDisk();
483 		}
484 
485 		return this.versions;
486 	}
487 
488 }