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